1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
use crate::prelude::*;
use std::time::Duration;

/// Ex:
/// ```
/// use shanimation_rs::prelude::*;
///
/// ClosureRenderable {
///    data: (),
///    process: |data, params, time, scene, abs_position| {
///        params.rotation = time.as_secs_f64() * 2.0;
///    },
///    shader: |data, frame, uv, time, abs_position| -> Rgba<u8> {
///        let p = uv.map_both(|v| (v * 255.0) as u8);
///        Rgba([255, p.x, p.y, 255])
///    },
/// };
///```
#[derive(Clone)]
pub struct ClosureBehaviour<T, P, S>
where
    T: Clone + Send + Sync,
    P: Fn(&mut T, &mut RenderableParams, Duration, &Scene, Point<isize>) + Clone + Send + Sync,
    S: Fn(&T, &Img, Point<f64>, Duration, Point<isize>) -> Rgba<u8> + Clone + Send + Sync,
{
    pub data: T,
    pub process: P,
    pub shader: S,
}

impl<T, P, S> Behaviour for ClosureBehaviour<T, P, S>
where
    T: Clone + Send + Sync,
    P: Fn(&mut T, &mut RenderableParams, Duration, &Scene, Point<isize>) + Clone + Send + Sync,
    S: Fn(&T, &Img, Point<f64>, Duration, Point<isize>) -> Rgba<u8> + Clone + Send + Sync,
{
    fn process(
        &mut self,
        params: &mut RenderableParams,
        time: Duration,
        scene: &Scene,
        abs_position: Point<isize>,
    ) {
        (self.process)(&mut self.data, params, time, scene, abs_position);
    }
    fn get_pixel(
        &self,
        current_frame: &Img,
        uv_coords: Point<f64>,
        time: Duration,
        abs_position: Point<isize>,
    ) -> Rgba<u8> {
        (self.shader)(&self.data, current_frame, uv_coords, time, abs_position)
    }
}