add staggered text

rename box to rect
refactor rust
This commit is contained in:
2023-05-23 10:27:45 +02:00
parent 7576850ae0
commit 8523e44029
32 changed files with 4344 additions and 2203 deletions

View File

@@ -0,0 +1,73 @@
use serde::{Deserialize, Serialize};
use crate::animation::{primitives::utils::timestamp_to_frame, timeline::Timeline};
use super::{
ellipse::{AnimatedEllipseEntity, EllipseEntity},
rect::{AnimatedRectEntity, RectEntity},
staggered_text::{AnimatedStaggeredTextEntity, StaggeredTextEntity},
text::{AnimatedTextEntity, TextEntity},
};
pub trait Drawable {
fn should_draw(&self, animation_data: &AnimationData, timeline: &Timeline) -> bool {
let start_frame = timestamp_to_frame(animation_data.offset, timeline.fps);
let end_frame = timestamp_to_frame(
animation_data.offset + animation_data.duration,
timeline.fps,
);
// println!("start {0} end {1}", start_frame, end_frame);
let is_before = timeline.render_state.curr_frame < start_frame;
let is_after = timeline.render_state.curr_frame > end_frame;
let is_between = !is_after && !is_before;
if is_between {
return true;
} else {
return false;
}
}
}
pub trait Animateable {
fn sort_keyframes(&mut self);
fn calculate(&mut self, timeline: &Timeline) -> Option<Entity>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum AnimatedEntity {
Text(AnimatedTextEntity),
StaggeredText(AnimatedStaggeredTextEntity),
Ellipse(AnimatedEllipseEntity),
Rect(AnimatedRectEntity),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Entity {
Text(TextEntity),
StaggeredText(StaggeredTextEntity),
Ellipse(EllipseEntity),
Rect(RectEntity),
}
impl AnimatedEntity {
pub fn calculate(&mut self, timeline: &Timeline) -> Option<Entity> {
match self {
Self::Text(text_entity) => text_entity.calculate(timeline),
Self::Rect(box_entity) => box_entity.calculate(timeline),
Self::StaggeredText(staggered_text_entity) => staggered_text_entity.calculate(timeline),
Self::Ellipse(ellipse_entity) => ellipse_entity.calculate(timeline),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnimationData {
pub offset: f32,
pub duration: f32,
pub visible: bool,
}

View File

@@ -0,0 +1,86 @@
use serde::{Deserialize, Serialize};
use crate::animation::{
primitives::{
paint::Paint,
transform::{AnimatedTransform, Transform},
values::{AnimatedFloatVec2, AnimatedValue},
},
timeline::Timeline,
};
use super::common::{Animateable, AnimationData, Drawable, Entity};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnimatedEllipseEntity {
pub paint: Paint,
pub radius: AnimatedFloatVec2,
pub origin: AnimatedFloatVec2,
pub position: AnimatedFloatVec2,
pub animation_data: AnimationData,
pub transform: Option<AnimatedTransform>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct EllipseEntity {
pub radius: (f32, f32),
pub position: (f32, f32),
pub origin: (f32, f32),
pub paint: Paint,
pub transform: Option<Transform>,
}
impl Drawable for AnimatedEllipseEntity {}
impl Animateable for AnimatedEllipseEntity {
fn calculate(&mut self, timeline: &Timeline) -> Option<Entity> {
let should_draw = self.should_draw(&self.animation_data, timeline);
if should_draw {
self.sort_keyframes();
let radius = self.radius.get_value_at_frame(
timeline.render_state.curr_frame,
&self.animation_data,
timeline.fps,
);
let position = self.position.get_value_at_frame(
timeline.render_state.curr_frame,
&self.animation_data,
timeline.fps,
);
let origin = self.origin.get_value_at_frame(
timeline.render_state.curr_frame,
&self.animation_data,
timeline.fps,
);
let transform: Option<Transform> = match self.transform.clone() {
Some(mut val) => Some(val.calculate(timeline, &self.animation_data)),
None => None,
};
Some(Entity::Ellipse(EllipseEntity {
radius,
position,
origin,
paint: self.paint.clone(),
transform,
}))
} else {
None
}
}
fn sort_keyframes(&mut self) {
let transform = self.transform.clone();
if let Some(mut transform) = transform {
transform.sort_keyframes();
}
self.position.sort_keyframes();
self.radius.sort_keyframes();
}
}

View File

@@ -0,0 +1,5 @@
pub mod common;
pub mod ellipse;
pub mod rect;
pub mod staggered_text;
pub mod text;

View File

@@ -0,0 +1,84 @@
use serde::{Deserialize, Serialize};
use crate::animation::{
primitives::{
paint::Paint,
transform::{AnimatedTransform, Transform},
values::{AnimatedFloatVec2, AnimatedValue},
},
timeline::Timeline,
};
use super::common::{Animateable, AnimationData, Drawable, Entity};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnimatedRectEntity {
pub position: AnimatedFloatVec2,
pub size: AnimatedFloatVec2,
pub origin: AnimatedFloatVec2,
pub paint: Paint,
pub animation_data: AnimationData,
pub transform: Option<AnimatedTransform>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RectEntity {
pub position: (f32, f32),
pub size: (f32, f32),
pub origin: (f32, f32),
pub paint: Paint,
pub transform: Option<Transform>,
}
impl Drawable for AnimatedRectEntity {}
impl Animateable for AnimatedRectEntity {
fn sort_keyframes(&mut self) {
if let Some(x) = &mut self.transform {
x.sort_keyframes();
}
self.position.sort_keyframes();
self.size.sort_keyframes();
}
fn calculate(&mut self, timeline: &Timeline) -> Option<Entity> {
let should_draw = self.should_draw(&self.animation_data, timeline);
if should_draw {
self.sort_keyframes();
let position = self.position.get_value_at_frame(
timeline.render_state.curr_frame,
&self.animation_data,
timeline.fps,
);
let size = self.size.get_value_at_frame(
timeline.render_state.curr_frame,
&self.animation_data,
timeline.fps,
);
let origin = self.origin.get_value_at_frame(
timeline.render_state.curr_frame,
&self.animation_data,
timeline.fps,
);
let transform: Option<Transform> = match self.transform.clone() {
Some(mut val) => Some(val.calculate(timeline, &self.animation_data)),
None => None,
};
Some(Entity::Rect(RectEntity {
position,
size,
origin,
paint: self.paint.clone(),
transform,
}))
} else {
None
}
}
}

View File

@@ -0,0 +1,83 @@
use super::common::{Animateable, AnimationData, Drawable, Entity};
use crate::animation::{
primitives::{
paint::TextPaint,
transform::{AnimatedTransform, Transform},
},
timeline::Timeline,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnimatedStaggeredTextLetter {
pub transform: Option<AnimatedTransform>,
pub paint: TextPaint,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StaggeredTextLetter {
pub transform: Option<Transform>,
pub paint: TextPaint,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnimatedStaggeredTextEntity {
pub text: String,
pub stagger: f32,
pub animation_data: AnimationData,
pub transform: Option<AnimatedTransform>,
pub letter: AnimatedStaggeredTextLetter,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StaggeredTextEntity {
pub text: String,
pub stagger: f32,
pub transform: Option<Transform>,
pub animation_data: AnimationData,
pub letter: StaggeredTextLetter,
}
impl Drawable for AnimatedStaggeredTextEntity {}
impl Animateable for AnimatedStaggeredTextEntity {
fn calculate(&mut self, timeline: &Timeline) -> Option<Entity> {
let should_draw: bool = self.should_draw(&self.animation_data, timeline);
if should_draw {
self.sort_keyframes();
let transform: Option<Transform> = match self.transform.clone() {
Some(mut val) => Some(val.calculate(timeline, &self.animation_data)),
None => None,
};
let letter_transform: Option<Transform> = match self.letter.transform.clone() {
Some(mut val) => Some(val.calculate(timeline, &self.animation_data)),
None => None,
};
Some(Entity::StaggeredText(StaggeredTextEntity {
transform,
stagger: self.stagger,
text: self.text.clone(),
animation_data: self.animation_data.clone(),
letter: StaggeredTextLetter {
transform: letter_transform,
paint: self.letter.paint.clone(),
},
}))
} else {
None
}
}
fn sort_keyframes(&mut self) {
if let Some(x) = &mut self.transform {
x.sort_keyframes();
}
if let Some(x) = &mut self.letter.transform {
x.sort_keyframes();
}
}
}

View File

@@ -0,0 +1,76 @@
use crate::animation::{
primitives::{
paint::TextPaint,
transform::{AnimatedTransform, Transform},
values::{AnimatedFloatVec2, AnimatedValue},
},
timeline::Timeline,
};
use serde::{Deserialize, Serialize};
use super::common::{Animateable, AnimationData, Drawable, Entity};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TextEntity {
pub text: String,
pub origin: (f32, f32),
pub paint: TextPaint,
pub transform: Option<Transform>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnimatedTextEntity {
pub text: String,
pub origin: AnimatedFloatVec2,
pub paint: TextPaint,
pub animation_data: AnimationData,
pub transform: Option<AnimatedTransform>,
}
impl Drawable for AnimatedTextEntity {}
impl AnimatedTextEntity {
fn into_static(&mut self, timeline: &Timeline) -> TextEntity {
self.sort_keyframes();
let origin = self.origin.get_value_at_frame(
timeline.render_state.curr_frame,
&self.animation_data,
timeline.fps,
);
let transform: Option<Transform> = match self.transform.clone() {
Some(mut val) => Some(val.calculate(timeline, &self.animation_data)),
None => None,
};
TextEntity {
transform,
text: self.text.clone(),
origin,
paint: self.paint.clone(),
}
}
}
impl Animateable for AnimatedTextEntity {
fn calculate(&mut self, timeline: &Timeline) -> Option<Entity> {
let should_draw = self.should_draw(&self.animation_data, timeline);
if should_draw {
self.sort_keyframes();
Some(Entity::Text(self.into_static(timeline)))
} else {
None
}
}
fn sort_keyframes(&mut self) {
if let Some(x) = &mut self.transform {
x.sort_keyframes();
}
self.origin.sort_keyframes();
}
}