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
/*
* // Copyright (c) 2021 Feng Yang
* //
* // I am making my contributions/submissions to this project solely in my
* // personal capacity and am not conveying any rights to any intellectual
* // property of any third parties.
*/
use std::sync::{RwLock, Arc};
use log::info;
use std::time::SystemTime;
///
/// # Representation of an animation frame.
///
/// This struct holds current animation frame index and frame interval in
/// seconds.
///
#[derive(Clone)]
pub struct Frame {
/// Frame index.
pub index: isize,
/// Time interval in seconds between two adjacent frames.
pub time_interval_in_seconds: f64,
}
impl Frame {
/// Constructs Frame instance with 1/60 seconds time interval.
pub fn new_default() -> Frame {
return Frame {
index: 0,
time_interval_in_seconds: 1.0 / 60.0,
};
}
/// Constructs Frame instance with given time interval.
pub fn new(new_index: isize, new_time_interval_in_seconds: f64) -> Frame {
return Frame {
index: new_index,
time_interval_in_seconds: new_time_interval_in_seconds,
};
}
/// Returns the elapsed time in seconds.
pub fn time_in_seconds(&self) -> f64 {
return self.index as f64 * self.time_interval_in_seconds;
}
/// Advances single frame.
pub fn advance_single(&mut self) {
self.index += 1;
}
/// Advances multiple frames.
/// - parameter: delta Number of frames to advance.
pub fn advance_multi(&mut self, delta: isize) {
self.index += delta;
}
}
//--------------------------------------------------------------------------------------------------
///
/// # Abstract base class for animation-related class.
///
/// This class represents the animation logic in very abstract level.
/// Generally animation is a function of time and/or its previous state.
/// This base class provides a virtual function update() which can be
/// overridden by its sub-classes to implement their own state update logic.
///
pub trait Animation {
///
/// ## Updates animation state for given frame.
///
/// This function updates animation state by calling Animation::on_update
/// function.
///
fn update(&mut self, frame: &Frame) {
let now = SystemTime::now();
info!("Begin updating frame: {} timeIntervalInSeconds: {} (1/{}) seconds",
frame.index, frame.time_interval_in_seconds, 1.0 / frame.time_interval_in_seconds);
self.on_update(frame);
info!("End updating frame (took {} seconds)", now.elapsed().unwrap().as_secs_f64());
}
///
/// ## The implementation of this function should update the animation state for given Frame instance **frame**.
///
/// This function is called from Animation::update when state of this class
/// instance needs to be updated. Thus, the inherited class should override
/// this function and implement its logic for updating the animation state.
///
fn on_update(&mut self, frame: &Frame);
}
/// Shared pointer for the Animation type.
pub type AnimationPtr = Arc<RwLock<dyn Animation>>;