Skip to main content

animato_js/
batch.rs

1//! CPU batch tween evaluation for JavaScript.
2
3use crate::easing::parse_easing;
4use crate::error::require_index;
5use crate::types::f32_array;
6use animato_core::Update;
7use animato_tween::Tween as CoreTween;
8use js_sys::Float32Array;
9use wasm_bindgen::prelude::*;
10
11/// Batched scalar tween evaluator.
12#[wasm_bindgen(js_name = TweenBatch)]
13#[derive(Clone, Debug, Default)]
14pub struct TweenBatch {
15    tweens: Vec<CoreTween<f32>>,
16    values: Vec<f32>,
17}
18
19#[wasm_bindgen(js_class = TweenBatch)]
20impl TweenBatch {
21    /// Create an empty batch.
22    #[wasm_bindgen(constructor)]
23    pub fn new() -> Self {
24        Self::default()
25    }
26
27    /// Push a tween and return its batch index.
28    pub fn push(
29        &mut self,
30        from: f32,
31        to: f32,
32        duration: f32,
33        easing: &str,
34    ) -> Result<u32, JsValue> {
35        let tween = CoreTween::new(from, to)
36            .duration(duration.max(0.0))
37            .easing(parse_easing(easing)?)
38            .build();
39        let index = self.tweens.len();
40        self.values.push(tween.value());
41        self.tweens.push(tween);
42        Ok(index as u32)
43    }
44
45    /// Advance every tween by `dt` seconds.
46    pub fn tick(&mut self, dt: f32) {
47        for (index, tween) in self.tweens.iter_mut().enumerate() {
48            tween.update(dt);
49            self.values[index] = tween.value();
50        }
51    }
52
53    /// Current value at index.
54    pub fn value(&self, index: u32) -> Result<f32, JsValue> {
55        Ok(self.values[require_index(index, self.values.len(), "batch")?])
56    }
57
58    /// All current values.
59    pub fn values(&self) -> Float32Array {
60        f32_array(&self.values)
61    }
62
63    /// Number of tweens.
64    pub fn len(&self) -> usize {
65        self.tweens.len()
66    }
67
68    /// Whether the batch is empty.
69    #[wasm_bindgen(js_name = isEmpty)]
70    pub fn is_empty(&self) -> bool {
71        self.tweens.is_empty()
72    }
73
74    /// Clear all tweens.
75    pub fn clear(&mut self) {
76        self.tweens.clear();
77        self.values.clear();
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn batch_updates_values() {
87        let mut batch = TweenBatch::new();
88        let id = batch.push(0.0, 10.0, 1.0, "linear").unwrap();
89        batch.tick(0.5);
90        assert_eq!(batch.value(id).unwrap(), 5.0);
91    }
92}