logo
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use std::{fmt, rc::Rc};

use crate::engine::d2::display::{ImageSprite, Sprite, Texture};

use super::Symbol;
/// Defines a flipbook-style movie, typically created from a spritesheet. Use
/// `Library.fromFlipbooks()` to create a Library from a list of Flipbooks.
#[derive(Default, Clone, Debug)]
pub struct Flipbook {
    pub name: String,
    pub frames: Vec<FlipbookFrame>,
}

impl Flipbook {
    /// @param name The name of the symbol that will be placed in the library.
    /// @param textures The frames of the flipbook animation.
    pub fn new<A: Texture + 'static>(name: String, textures: Vec<Rc<A>>) -> Self {
        let mut instance = Self {
            name,
            frames: Vec::new(),
        };

        // By default, play the animation for one second
        let duration_per_frame = 1.0 / textures.len() as f32;
        for texture in textures {
            instance.frames.push(FlipbookFrame::new(
                (texture as Rc<dyn Texture>).clone(),
                duration_per_frame,
            ));
        }
        instance
    }

    /// Uniformly sets the duration for all frames in this flipbook, so that the entire movie takes
    /// the given duration.
    ///  *
    /// @param duration The movie duration, in seconds.
    /// @returns This instance, for chaining.
    pub fn set_duration(&mut self, duration: f32) -> &Self {
        let duration_per_frame = duration / self.frames.len() as f32;
        for frame in self.frames.iter_mut() {
            frame.duration = duration_per_frame;
        }

        self
    }

    /// Sets the anchor point for all frames in this flipbook.
    ///  *
    /// @returns This instance, for chaining.
    pub fn set_anchor(&mut self, x: f32, y: f32) -> &Self {
        for frame in self.frames.iter_mut() {
            frame.anchor_x = x;
            frame.anchor_y = y;
        }

        self
    }
}

#[derive(Clone, Debug)]
pub struct FlipbookFrame {
    /// The texture shown during this frame.
    pub texture: Rc<dyn Texture>,

    /// How long to show this frame, in seconds.
    pub duration: f32,

    /// The X position of this frame's anchor point.
    pub anchor_x: f32,

    /// The Y position of this frame's anchor point.
    pub anchor_y: f32,

    pub label: Option<String>,
}

impl FlipbookFrame {
    fn new(texture: Rc<dyn Texture>, duration: f32) -> Self {
        Self {
            texture,
            duration,
            anchor_x: 0.0,
            anchor_y: 0.0,
            label: None,
        }
    }

    fn to_symbol(&self) -> FrameSymbol {
        // impl Symbol<Sprite>
        FrameSymbol::new(self)
    }
}

pub struct FrameSymbol {
    pub name: String,
    texture: Rc<dyn Texture>,
    anchor_x: f32,
    anchor_y: f32,
}

impl FrameSymbol {
    pub fn new(frame: &FlipbookFrame) -> Self {
        Self {
            texture: frame.texture.clone(),
            anchor_x: frame.anchor_x,
            anchor_y: frame.anchor_y,
            name: String::new(),
        }
    }
}

impl Symbol<ImageSprite> for FrameSymbol {
    fn name(&self) -> Option<String> {
        None
    }

    fn create_sprite(&self) -> ImageSprite {
        let mut sprite = ImageSprite::new(Some(self.texture.clone()));
        sprite.inner.set_anchor(self.anchor_x, self.anchor_y);

        sprite
    }
}

impl fmt::Debug for FrameSymbol {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("FrameSymbol")
            //  .field("x", &self.x)
            //  .field("y", &self.y)
            .finish()
    }
}