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>>;