|
use std::time::Duration; |
|
|
|
use crate::messages::prelude::*; |
|
|
|
use super::TimingInformation; |
|
|
|
#[derive(PartialEq, Clone, Default, Debug, serde::Serialize, serde::Deserialize)] |
|
pub enum AnimationTimeMode { |
|
#[default] |
|
TimeBased, |
|
FrameBased, |
|
} |
|
|
|
#[derive(Default, Debug, Clone, PartialEq)] |
|
enum AnimationState { |
|
#[default] |
|
Stopped, |
|
Playing { |
|
start: f64, |
|
}, |
|
Paused { |
|
start: f64, |
|
pause_time: f64, |
|
}, |
|
} |
|
|
|
#[derive(Default, Debug, Clone, PartialEq)] |
|
pub struct AnimationMessageHandler { |
|
|
|
live_preview_recently_zero: bool, |
|
timestamp: f64, |
|
frame_index: f64, |
|
animation_state: AnimationState, |
|
fps: f64, |
|
animation_time_mode: AnimationTimeMode, |
|
} |
|
impl AnimationMessageHandler { |
|
pub(crate) fn timing_information(&self) -> TimingInformation { |
|
let animation_time = self.timestamp - self.animation_start(); |
|
let animation_time = match self.animation_time_mode { |
|
AnimationTimeMode::TimeBased => Duration::from_millis(animation_time as u64), |
|
AnimationTimeMode::FrameBased => Duration::from_secs((self.frame_index / self.fps) as u64), |
|
}; |
|
TimingInformation { time: self.timestamp, animation_time } |
|
} |
|
|
|
pub(crate) fn animation_start(&self) -> f64 { |
|
match self.animation_state { |
|
AnimationState::Stopped => self.timestamp, |
|
AnimationState::Playing { start } => start, |
|
AnimationState::Paused { start, pause_time } => start + self.timestamp - pause_time, |
|
} |
|
} |
|
|
|
pub fn is_playing(&self) -> bool { |
|
matches!(self.animation_state, AnimationState::Playing { .. }) |
|
} |
|
} |
|
|
|
impl MessageHandler<AnimationMessage, ()> for AnimationMessageHandler { |
|
fn process_message(&mut self, message: AnimationMessage, responses: &mut VecDeque<Message>, _data: ()) { |
|
match message { |
|
AnimationMessage::ToggleLivePreview => match self.animation_state { |
|
AnimationState::Stopped => responses.add(AnimationMessage::EnableLivePreview), |
|
AnimationState::Playing { .. } => responses.add(AnimationMessage::DisableLivePreview), |
|
AnimationState::Paused { .. } => responses.add(AnimationMessage::EnableLivePreview), |
|
}, |
|
AnimationMessage::EnableLivePreview => { |
|
self.animation_state = AnimationState::Playing { start: self.animation_start() }; |
|
|
|
|
|
responses.add(PortfolioMessage::UpdateDocumentWidgets); |
|
} |
|
AnimationMessage::DisableLivePreview => { |
|
match self.animation_state { |
|
AnimationState::Stopped => (), |
|
AnimationState::Playing { start } => self.animation_state = AnimationState::Paused { start, pause_time: self.timestamp }, |
|
AnimationState::Paused { .. } => (), |
|
} |
|
|
|
|
|
responses.add(PortfolioMessage::UpdateDocumentWidgets); |
|
} |
|
AnimationMessage::SetFrameIndex(frame) => { |
|
self.frame_index = frame; |
|
responses.add(PortfolioMessage::SubmitActiveGraphRender); |
|
|
|
responses.add(PortfolioMessage::UpdateDocumentWidgets); |
|
} |
|
AnimationMessage::SetTime(time) => { |
|
self.timestamp = time; |
|
responses.add(AnimationMessage::UpdateTime); |
|
} |
|
AnimationMessage::IncrementFrameCounter => { |
|
if self.is_playing() { |
|
self.frame_index += 1.; |
|
responses.add(AnimationMessage::UpdateTime); |
|
} |
|
} |
|
AnimationMessage::UpdateTime => { |
|
if self.is_playing() { |
|
responses.add(PortfolioMessage::SubmitActiveGraphRender); |
|
|
|
if self.live_preview_recently_zero { |
|
|
|
responses.add(PortfolioMessage::UpdateDocumentWidgets); |
|
self.live_preview_recently_zero = false; |
|
} |
|
} |
|
} |
|
AnimationMessage::RestartAnimation => { |
|
self.frame_index = 0.; |
|
self.animation_state = match self.animation_state { |
|
AnimationState::Playing { .. } => AnimationState::Playing { start: self.timestamp }, |
|
_ => AnimationState::Stopped, |
|
}; |
|
self.live_preview_recently_zero = true; |
|
responses.add(PortfolioMessage::SubmitActiveGraphRender); |
|
|
|
responses.add(PortfolioMessage::UpdateDocumentWidgets); |
|
} |
|
AnimationMessage::SetAnimationTimeMode(animation_time_mode) => { |
|
self.animation_time_mode = animation_time_mode; |
|
} |
|
} |
|
} |
|
|
|
advertise_actions!(AnimationMessageDiscriminant; |
|
ToggleLivePreview, |
|
SetFrameIndex, |
|
RestartAnimation, |
|
); |
|
} |
|
|