use crate::preludes::widget_creation::*;
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum AnimationContainerSequence<A: crate::Animation> {
Single(A),
Many(Vec<A>),
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct AnimationContainer<W: Widget, A: crate::Animation> {
pub widget: W,
pub sequence: AnimationContainerSequence<A>,
index: usize,
prev_transform: Option<Transform>,
new_start_transform: Option<Transform>,
is_playing: bool,
paused_time: Option<std::time::Instant>,
paused_duration: std::time::Duration,
is_done: bool,
widget_data: WidgetData,
}
impl<W: Widget, A: crate::Animation> AnimationContainer<W, A> {
pub fn new(sequence: AnimationContainerSequence<A>, autoplay: bool, widget: W) -> Self {
Self {
widget,
sequence,
index: 0,
prev_transform: None,
new_start_transform: None,
is_playing: autoplay,
paused_time: None,
paused_duration: std::time::Duration::ZERO,
is_done: false,
widget_data: WidgetData::new(),
}
}
pub fn play(&mut self) {
if self.is_playing == false {
self.is_playing = true;
if let Some(paused_time) = self.paused_time {
let duration = std::time::Instant::now() - paused_time;
self.paused_duration += duration;
}
else {
self.soft_reset();
}
}
}
pub fn pause(&mut self) {
if self.is_playing {
self.is_playing = false;
self.paused_time = Some(std::time::Instant::now());
}
}
pub fn is_playing(&self) -> bool {
return self.is_playing;
}
pub fn has_finished(&self) -> bool {
return self.is_done;
}
pub fn reset(&mut self, autoplay: bool) {
self.index = 0;
self.is_done = false;
self.is_playing = autoplay;
self.soft_reset();
}
fn soft_reset(&mut self) {
self.paused_time = None;
self.paused_duration = std::time::Duration::ZERO;
self.widget.widget_data().animation_data.reset();
}
}
impl<W: Widget, A: crate::Animation> Widget for AnimationContainer<W, A> {
fn draw(&mut self, canvas: &mut Canvas) {
let is_playing = self.is_playing();
let is_done = self.has_finished();
let child_data = self.widget.widget_data();
let static_rest = self.prev_transform.unwrap_or(canvas.original_transform());
if is_playing && is_done == false {
let offset: f64 = -self.paused_duration.as_secs_f64();
let (animation, is_single) = match self.sequence {
AnimationContainerSequence::Single(ref mut single) => (Some(single), true),
AnimationContainerSequence::Many(ref mut many) => (many.get_mut(self.index), false),
};
if let Some(animation) = animation {
canvas.animate_with_offset(
animation,
&child_data.animation_data,
self.new_start_transform,
offset
);
self.prev_transform = Some(canvas.transform);
if animation.is_done(
child_data.animation_data.duration()
.as_secs_f64() + offset,
) {
if is_single {
self.is_done = true;
} else {
self.index += 1;
self.new_start_transform = Some(canvas.transform);
self.soft_reset();
}
}
}
else {
self.is_done = true;
canvas.transform = static_rest;
}
}
else {
canvas.transform = static_rest;
}
self.widget.draw(canvas);
}
fn widget_info(&self) -> WidgetInfo {
return self.widget.widget_info();
}
fn widget_data(&mut self) -> &mut WidgetData {
return &mut self.widget_data;
}
}