remove tauri rust src and replace with lib
All checks were successful
continuous-integration/drone/push Build is passing

remove empty files
This commit is contained in:
Enrico Bühler 2023-06-27 16:46:54 +02:00
parent 1d9508f49b
commit fa3f7a8403
27 changed files with 85 additions and 1829 deletions

View File

@ -22,6 +22,7 @@
"@radix-ui/react-toolbar": "^1.0.3", "@radix-ui/react-toolbar": "^1.0.3",
"@tauri-apps/api": "^1.3.0", "@tauri-apps/api": "^1.3.0",
"@tempblade/common": "^2.0.1", "@tempblade/common": "^2.0.1",
"@types/d3-array": "^3.0.5",
"@types/lodash.set": "^4.3.7", "@types/lodash.set": "^4.3.7",
"@unom/style": "^0.2.14", "@unom/style": "^0.2.14",
"@visx/axis": "^3.1.0", "@visx/axis": "^3.1.0",

View File

@ -418,6 +418,20 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "creator_rs"
version = "0.1.0"
dependencies = [
"font-kit",
"rayon",
"serde",
"serde_json",
"simple-easing",
"tauri",
"uuid",
"wasm-bindgen",
]
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.5.8" version = "0.5.8"
@ -441,14 +455,14 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-epoch" name = "crossbeam-epoch"
version = "0.9.14" version = "0.9.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"cfg-if", "cfg-if",
"crossbeam-utils", "crossbeam-utils",
"memoffset", "memoffset 0.9.0",
"scopeguard", "scopeguard",
] ]
@ -645,9 +659,9 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
[[package]] [[package]]
name = "dlib" name = "dlib"
version = "0.5.0" version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
dependencies = [ dependencies = [
"libloading", "libloading",
] ]
@ -764,7 +778,7 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535" checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535"
dependencies = [ dependencies = [
"memoffset", "memoffset 0.8.0",
"rustc_version 0.4.0", "rustc_version 0.4.0",
] ]
@ -1081,8 +1095,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"js-sys",
"libc", "libc",
"wasi 0.11.0+wasi-snapshot-preview1", "wasi 0.11.0+wasi-snapshot-preview1",
"wasm-bindgen",
] ]
[[package]] [[package]]
@ -1547,12 +1563,12 @@ checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
[[package]] [[package]]
name = "libloading" name = "libloading"
version = "0.7.4" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"winapi", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@ -1694,6 +1710,15 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "memoffset"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.7.1" version = "0.7.1"
@ -1966,9 +1991,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]] [[package]]
name = "pest" name = "pest"
version = "2.6.0" version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70" checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9"
dependencies = [ dependencies = [
"thiserror", "thiserror",
"ucd-trie", "ucd-trie",
@ -2570,11 +2595,11 @@ dependencies = [
[[package]] [[package]]
name = "serde_with" name = "serde_with"
version = "2.3.3" version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" checksum = "9f02d8aa6e3c385bf084924f660ce2a3a6bd333ba55b35e8590b321f35d88513"
dependencies = [ dependencies = [
"base64 0.13.1", "base64 0.21.0",
"chrono", "chrono",
"hex", "hex",
"indexmap", "indexmap",
@ -2586,9 +2611,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_with_macros" name = "serde_with_macros"
version = "2.3.3" version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" checksum = "edc7d5d3932fb12ce722ee5e64dd38c504efba37567f0c402f6ca728c3b8b070"
dependencies = [ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
@ -2881,9 +2906,9 @@ checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5"
[[package]] [[package]]
name = "tauri" name = "tauri"
version = "1.3.0" version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d42ba3a2e8556722f31336a0750c10dbb6a81396a1c452977f515da83f69f842" checksum = "7fbe522898e35407a8e60dc3870f7579fea2fc262a6a6072eccdd37ae1e1d91e"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cocoa", "cocoa",
@ -2929,9 +2954,9 @@ dependencies = [
[[package]] [[package]]
name = "tauri-build" name = "tauri-build"
version = "1.3.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "929b3bd1248afc07b63e33a6a53c3f82c32d0b0a5e216e4530e94c467e019389" checksum = "7d2edd6a259b5591c8efdeb9d5702cb53515b82a6affebd55c7fd6d3a27b7d1b"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cargo_toml", "cargo_toml",
@ -2942,14 +2967,13 @@ dependencies = [
"serde_json", "serde_json",
"tauri-utils", "tauri-utils",
"tauri-winres", "tauri-winres",
"winnow",
] ]
[[package]] [[package]]
name = "tauri-codegen" name = "tauri-codegen"
version = "1.3.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5a2105f807c6f50b2fa2ce5abd62ef207bc6f14c9fcc6b8caec437f6fb13bde" checksum = "54ad2d49fdeab4a08717f5b49a163bdc72efc3b1950b6758245fcde79b645e1a"
dependencies = [ dependencies = [
"base64 0.21.0", "base64 0.21.0",
"brotli", "brotli",
@ -2973,9 +2997,9 @@ dependencies = [
[[package]] [[package]]
name = "tauri-macros" name = "tauri-macros"
version = "1.3.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8784cfe6f5444097e93c69107d1ac5e8f13d02850efa8d8f2a40fe79674cef46" checksum = "8eb12a2454e747896929338d93b0642144bb51e0dddbb36e579035731f0d76b7"
dependencies = [ dependencies = [
"heck 0.4.1", "heck 0.4.1",
"proc-macro2", "proc-macro2",
@ -2987,9 +3011,9 @@ dependencies = [
[[package]] [[package]]
name = "tauri-runtime" name = "tauri-runtime"
version = "0.13.0" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3b80ea3fcd5fefb60739a3b577b277e8fc30434538a2f5bba82ad7d4368c422" checksum = "108683199cb18f96d2d4134187bb789964143c845d2d154848dda209191fd769"
dependencies = [ dependencies = [
"gtk", "gtk",
"http", "http",
@ -3008,9 +3032,9 @@ dependencies = [
[[package]] [[package]]
name = "tauri-runtime-wry" name = "tauri-runtime-wry"
version = "0.13.0" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1c396950b1ba06aee1b4ffe6c7cd305ff433ca0e30acbc5fa1a2f92a4ce70f1" checksum = "0b7aa256a1407a3a091b5d843eccc1a5042289baf0a43d1179d9f0fcfea37c1b"
dependencies = [ dependencies = [
"cocoa", "cocoa",
"gtk", "gtk",
@ -3028,12 +3052,13 @@ dependencies = [
[[package]] [[package]]
name = "tauri-utils" name = "tauri-utils"
version = "1.3.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a6f9c2dafef5cbcf52926af57ce9561bd33bb41d7394f8bb849c0330260d864" checksum = "03fc02bb6072bb397e1d473c6f76c953cda48b4a2d0cce605df284aa74a12e84"
dependencies = [ dependencies = [
"brotli", "brotli",
"ctor", "ctor",
"dunce",
"glob", "glob",
"heck 0.4.1", "heck 0.4.1",
"html5ever", "html5ever",
@ -3068,16 +3093,13 @@ dependencies = [
name = "tempblade-creator-app" name = "tempblade-creator-app"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"font-kit", "creator_rs",
"logging_timer", "logging_timer",
"rayon",
"serde", "serde",
"serde_json", "serde_json",
"simple-easing",
"tauri", "tauri",
"tauri-build", "tauri-build",
"tint", "tint",
"uuid",
] ]
[[package]] [[package]]
@ -3382,15 +3404,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
dependencies = [ dependencies = [
"getrandom 0.2.9", "getrandom 0.2.9",
"rand 0.8.5",
"uuid-macro-internal", "uuid-macro-internal",
"wasm-bindgen",
] ]
[[package]] [[package]]
name = "uuid-macro-internal" name = "uuid-macro-internal"
version = "1.3.3" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f67b459f42af2e6e1ee213cb9da4dbd022d3320788c3fb3e1b893093f1e45da" checksum = "8614dda80b9075fbca36bc31b58d1447715b1236af98dee21db521c47a0cc2c0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -10,20 +10,20 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies] [build-dependencies]
tauri-build = { version = "1.3", features = [] } tauri-build = { version = "1.4", features = [] }
[dependencies] [dependencies]
creator_core = { path = "../../lib/creator_rs", features = [
uuid = { version = "1.3.3", features = ["v4", "fast-rng", "macro-diagnostics"] } "fonts",
tauri = { version = "1.3", features = ["dialog-open", "dialog-save", "shell-open"] } "parallelization",
"tauri",
], version = "*", package = "creator_rs" }
tauri = { version = "1.4", features = ["dialog-open", "dialog-save", "shell-open"] }
serde = { version = "1.0", features = ["derive", "rc"] } serde = { version = "1.0", features = ["derive", "rc"] }
serde_json = "1.0" serde_json = "1.0"
tint = "1.0.0" tint = "1.0.0"
simple-easing = "1.0.1"
logging_timer = "1.1.0" logging_timer = "1.1.0"
rayon = "1.7"
font-kit = "0.11.0"
[features] [features]
# this feature is used for production builds or when `devPath` points to the filesystem # this feature is used for production builds or when `devPath` points to the filesystem

View File

@ -1,2 +0,0 @@
pub mod primitives;
pub mod timeline;

View File

@ -1,36 +0,0 @@
impl Animateable for AnimatedCircularText<'_> {
fn draw(&mut self, mut canvas: &mut Canvas, timeline: &Timeline<'_>) {
self.prepare(&mut canvas, &self.animation_data);
self.sort_keyframes();
self.paint.set_anti_alias(true);
let default_text_typeface = &Typeface::default();
let default_text_font = &Font::from_typeface(default_text_typeface, 190.0);
let text_font: &Font = match self.font {
Some(font) => font,
None => default_text_font,
};
let radius: f32 = 0.35 * timeline.size.0.min(timeline.size.1) as f32;
let mut path = Path::new();
path.add_circle(
(timeline.size.0 / 2, timeline.size.1 / 2),
radius,
PathDirection::CW,
);
let text_width = text_font.measure_str(self.text, Some(&self.paint));
canvas.draw
}
fn sort_keyframes(&mut self) {
self.origin.sort_keyframes();
}
}

View File

@ -1,78 +0,0 @@
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, PartialEq)]
pub struct Cache {
pub valid: bool,
}
#[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

@ -1,92 +0,0 @@
use serde::{Deserialize, Serialize};
use crate::animation::{
primitives::{
paint::Paint,
transform::{AnimatedTransform, Transform},
values::{AnimatedFloatVec2, AnimatedValue},
},
timeline::Timeline,
};
use super::common::{Animateable, AnimationData, Cache, Drawable, Entity};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnimatedEllipseEntity {
pub paint: Paint,
pub id: String,
pub cache: Cache,
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 cache: Cache,
pub id: String,
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 {
id: self.id.clone(),
radius,
position,
origin,
cache: self.cache.clone(),
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

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

View File

@ -1,90 +0,0 @@
use serde::{Deserialize, Serialize};
use crate::animation::{
primitives::{
paint::Paint,
transform::{AnimatedTransform, Transform},
values::{AnimatedFloatVec2, AnimatedValue},
},
timeline::Timeline,
};
use super::common::{Animateable, AnimationData, Cache, Drawable, Entity};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnimatedRectEntity {
pub id: String,
pub cache: Cache,
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 id: String,
pub cache: Cache,
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 {
id: self.id.clone(),
cache: self.cache.clone(),
position,
size,
origin,
paint: self.paint.clone(),
transform,
}))
} else {
None
}
}
}

View File

@ -1,112 +0,0 @@
use super::common::{Animateable, AnimationData, Cache, Drawable, Entity};
use crate::animation::{
primitives::{
paint::TextPaint,
transform::{AnimatedTransform, Transform},
values::{AnimatedFloatVec2, AnimatedValue},
},
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<Vec<Transform>>,
pub paint: TextPaint,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnimatedStaggeredTextEntity {
pub id: String,
pub cache: Cache,
pub text: String,
pub stagger: f32,
pub origin: AnimatedFloatVec2,
pub animation_data: AnimationData,
pub transform: Option<AnimatedTransform>,
pub letter: AnimatedStaggeredTextLetter,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StaggeredTextEntity {
pub id: String,
pub cache: Cache,
pub text: String,
pub stagger: f32,
pub origin: (f32, 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,
};
// Iterate over the chars of the string and calculate the animation with the staggered offset
let letter_transform: Option<Vec<Transform>> = match self.letter.transform.clone() {
Some(mut val) => {
let mut transforms: Vec<Transform> = Vec::new();
for c in self.text.chars().enumerate() {
let mut animation_data = self.animation_data.clone();
animation_data.offset += self.stagger * c.0 as f32;
let transform = val.calculate(timeline, &animation_data);
transforms.push(transform);
}
Some(transforms)
}
None => None,
};
let origin = self.origin.get_value_at_frame(
timeline.render_state.curr_frame,
&self.animation_data,
timeline.fps,
);
Some(Entity::StaggeredText(StaggeredTextEntity {
id: self.id.clone(),
transform,
cache: self.cache.clone(),
stagger: self.stagger,
origin,
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

@ -1,82 +0,0 @@
use crate::animation::{
primitives::{
paint::TextPaint,
transform::{AnimatedTransform, Transform},
values::{AnimatedFloatVec2, AnimatedValue},
},
timeline::Timeline,
};
use serde::{Deserialize, Serialize};
use super::common::{Animateable, AnimationData, Cache, Drawable, Entity};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TextEntity {
pub id: String,
pub cache: Cache,
pub text: String,
pub origin: (f32, f32),
pub paint: TextPaint,
pub transform: Option<Transform>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnimatedTextEntity {
pub id: String,
pub cache: Cache,
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 {
id: self.id.clone(),
cache: self.cache.clone(),
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();
}
}

View File

@ -1,170 +0,0 @@
use std::cmp::Ordering;
use super::keyframe::RenderedKeyframe;
use serde::{Deserialize, Serialize};
use simple_easing::{
circ_in, circ_in_out, circ_out, cubic_in, cubic_in_out, cubic_out, expo_in, expo_in_out,
expo_out, quad_in, quad_in_out, quad_out, quart_in, quart_in_out, quart_out, quint_in,
quint_in_out, quint_out,
};
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub struct SpringProperties {
pub mass: f32,
pub damping: f32,
pub stiffness: f32,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub struct SpringState {
pub velocity: f32,
pub last_val: f32,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
#[serde(tag = "easing_function")]
pub enum EasingFunction {
QuintOut,
QuintIn,
QuintInOut,
CircOut,
CircIn,
CircInOut,
CubicOut,
CubicIn,
CubicInOut,
ExpoOut,
ExpoIn,
ExpoInOut,
QuadOut,
QuadIn,
QuadInOut,
QuartOut,
QuartIn,
QuartInOut,
}
impl EasingFunction {
fn ease(self: &Self, t: f32) -> f32 {
match self {
EasingFunction::QuintOut => quint_out(t),
EasingFunction::QuintIn => quint_in(t),
EasingFunction::QuintInOut => quint_in_out(t),
EasingFunction::CircOut => circ_out(t),
EasingFunction::CircIn => circ_in(t),
EasingFunction::CircInOut => circ_in_out(t),
EasingFunction::CubicOut => cubic_out(t),
EasingFunction::CubicIn => cubic_in(t),
EasingFunction::CubicInOut => cubic_in_out(t),
EasingFunction::ExpoOut => expo_out(t),
EasingFunction::ExpoIn => expo_in(t),
EasingFunction::ExpoInOut => expo_in_out(t),
EasingFunction::QuadOut => quad_out(t),
EasingFunction::QuadIn => quad_in(t),
EasingFunction::QuadInOut => quad_in_out(t),
EasingFunction::QuartOut => quart_out(t),
EasingFunction::QuartIn => quart_in(t),
EasingFunction::QuartInOut => quart_in_out(t),
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type")]
pub enum InterpolationType {
Linear,
Spring(SpringProperties),
EasingFunction(EasingFunction),
}
pub fn calculate_spring_value(
curr_frame: i32,
start_value: f32,
target_value: f32,
start_frame: i32,
_end_frame: i32,
spring_props: &SpringProperties,
) -> f32 {
const PRECISION: f32 = 0.01;
const STEP: f32 = 10.0;
const REST_VELOCITY: f32 = PRECISION / 10.0;
let _is_growing = match start_value.total_cmp(&target_value) {
Ordering::Equal => false,
Ordering::Less => false,
Ordering::Greater => true,
};
let mut _is_moving = false;
let mut spring_state = SpringState {
last_val: start_value,
velocity: 0.0,
};
let mut position = start_value;
let relative_curr_frame = curr_frame - start_frame;
// println!("target_value {target_value} start_value {start_value}");
// println!("start_frame {start_frame} end_frame {end_frame}");
for _ in 0..relative_curr_frame {
let _is_moving = spring_state.velocity.abs() > REST_VELOCITY;
let spring_force = -spring_props.stiffness * 0.000001 * (position - target_value);
let damping_force = -spring_props.damping * 0.001 * spring_state.velocity;
let acceleration = (spring_force + damping_force) / spring_props.mass; // pt/ms^2
spring_state.velocity = spring_state.velocity + acceleration * STEP; // pt/ms
position = position + spring_state.velocity * STEP;
// println!("{position}")
}
position
}
pub fn interpolate_rendered_keyframes(
first_ren_keyframe: &RenderedKeyframe,
second_ren_keyframe: &RenderedKeyframe,
curr_frame: i32,
interpolation_type: InterpolationType,
_fps: i16,
) -> f32 {
let frame_range = second_ren_keyframe.absolute_frame - first_ren_keyframe.absolute_frame;
let position_in_range = curr_frame - first_ren_keyframe.absolute_frame;
let progress: f32 = (1.0 / frame_range as f32) * position_in_range as f32;
/* println!(
"Progress:{0} Frame_Range: {1} Position_In_Range: {2}",
progress, frame_range, position_in_range
); */
let value_diff = second_ren_keyframe.keyframe.value - first_ren_keyframe.keyframe.value;
match interpolation_type {
InterpolationType::Linear => {
let interpolated_val =
first_ren_keyframe.keyframe.value + (value_diff * progress as f32);
return interpolated_val;
}
InterpolationType::EasingFunction(easing_function) => {
let eased_progress = easing_function.ease(progress);
let interpolated_val =
first_ren_keyframe.keyframe.value + (value_diff * eased_progress as f32);
return interpolated_val;
}
InterpolationType::Spring(spring_properties) => {
let interpolated_value = calculate_spring_value(
curr_frame,
first_ren_keyframe.keyframe.value,
second_ren_keyframe.keyframe.value,
first_ren_keyframe.absolute_frame,
second_ren_keyframe.absolute_frame,
&spring_properties,
);
return interpolated_value;
}
};
}

View File

@ -1,157 +0,0 @@
use std::{cmp::Ordering, sync::Arc};
use serde::{Deserialize, Serialize};
use super::{
entities::common::AnimationData,
interpolations::{interpolate_rendered_keyframes, InterpolationType},
utils::render_keyframe,
};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Keyframe {
pub value: f32,
pub offset: f32,
pub id: Arc<str>,
pub interpolation: Option<InterpolationType>,
}
impl Keyframe {
pub fn new(
value: f32,
offset: f32,
id: Arc<str>,
interpolation: Option<InterpolationType>,
) -> Self {
Keyframe {
value,
offset,
id,
interpolation,
}
}
}
#[derive(Debug, Clone)]
pub struct RenderedKeyframe {
pub absolute_frame: i32,
pub keyframe: Keyframe,
pub index: usize,
pub distance_from_curr: i32,
pub abs_distance_from_curr: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Keyframes {
pub values: Vec<Keyframe>,
}
impl Keyframes {
pub fn get_value_at_frame(
&self,
curr_frame: i32,
animation_data: &AnimationData,
fps: i16,
) -> f32 {
let keyframe_count = self.values.len();
if keyframe_count > 0 {
let mut rendered_keyframes: Vec<RenderedKeyframe> = self
.values
.to_vec()
.into_iter()
.enumerate()
.map(|(index, keyframe)| {
render_keyframe(keyframe, animation_data, index, curr_frame, fps)
})
.collect();
rendered_keyframes
.sort_by(|a, b| a.abs_distance_from_curr.cmp(&b.abs_distance_from_curr));
let closest_keyframe = rendered_keyframes.get(0).unwrap();
let result = match (closest_keyframe.distance_from_curr).cmp(&0) {
Ordering::Equal => closest_keyframe.keyframe.value,
Ordering::Greater => {
if closest_keyframe.absolute_frame == curr_frame {
return closest_keyframe.keyframe.value;
} else {
let previous_keyframe =
rendered_keyframes.to_vec().into_iter().find(|keyframe| {
if closest_keyframe.index > 0 {
keyframe.index == closest_keyframe.index - 1
} else {
false
}
});
if let Some(previous_keyframe) = previous_keyframe {
let interpolation = match previous_keyframe.keyframe.interpolation {
Some(val) => val,
None => InterpolationType::Linear,
};
let interpolated_value = interpolate_rendered_keyframes(
&previous_keyframe,
closest_keyframe,
curr_frame,
interpolation,
fps,
);
return interpolated_value;
} else {
if closest_keyframe.absolute_frame > curr_frame {
return closest_keyframe.keyframe.value;
} else {
return 0.0;
}
}
}
}
Ordering::Less => {
if closest_keyframe.absolute_frame == curr_frame {
return closest_keyframe.keyframe.value;
} else {
let next_keyframe = rendered_keyframes
.to_vec()
.into_iter()
.find(|keyframe| keyframe.index == closest_keyframe.index + 1);
if let Some(next_keyframe) = next_keyframe {
let interpolation = match closest_keyframe.keyframe.interpolation {
Some(val) => val,
None => InterpolationType::Linear,
};
let interpolated_value = interpolate_rendered_keyframes(
closest_keyframe,
&next_keyframe,
curr_frame,
interpolation,
fps,
);
return interpolated_value;
} else {
if closest_keyframe.absolute_frame < curr_frame {
return closest_keyframe.keyframe.value;
} else {
return 0.0;
}
}
}
}
};
result
} else {
0.0
}
}
pub fn sort(&mut self) {
self.values.sort_by(|a, b| a.offset.total_cmp(&b.offset));
}
}

View File

@ -1,8 +0,0 @@
pub mod entities;
pub mod interpolations;
pub mod keyframe;
pub mod paint;
pub mod tests;
pub mod transform;
pub mod utils;
pub mod values;

View File

@ -1,70 +0,0 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Color {
value: (u8, u8, u8, f32),
}
impl Color {
pub fn new(red: u8, green: u8, blue: u8, alpha: f32) -> Color {
Color {
value: (red, green, blue, alpha),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum PaintStyle {
Fill(FillStyle),
Stroke(StrokeStyle),
StrokeAndFill(StrokeAndFillStyle),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Paint {
pub style: PaintStyle,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TextPaint {
pub style: PaintStyle,
pub align: TextAlign,
pub font_name: String,
pub size: f32,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StrokeStyle {
pub color: Color,
pub width: f32,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StrokeAndFillStyle {
pub stroke: StrokeStyle,
pub fill: FillStyle,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FillStyle {
pub color: Color,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum TextAlign {
Left,
Center,
Right,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FontDefinition {
pub family_name: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Font {
pub glyph_count: i32,
pub weight: i32,
pub style: String,
}

View File

@ -1,183 +0,0 @@
#[cfg(test)]
use crate::animation::primitives::{
entities::common::AnimationData,
interpolations::{calculate_spring_value, SpringProperties},
keyframe::{Keyframe, Keyframes},
utils::timestamp_to_frame,
};
#[test]
fn interpolates_the_input() {
use crate::animation::primitives::{
interpolations::{interpolate_rendered_keyframes, InterpolationType},
keyframe::{Keyframe, Keyframes, RenderedKeyframe},
utils::render_keyframe,
};
let animation_data = AnimationData {
offset: 0.0,
duration: 3.0,
visible: true,
};
let fps = 60;
let keyframes1 = Keyframes {
values: vec![
Keyframe {
id: "1".into(),
value: 0.0,
offset: 0.0,
interpolation: None,
},
Keyframe {
id: "2".into(),
value: 100.0,
offset: 1.0,
interpolation: None,
},
Keyframe {
id: "3".into(),
value: 300.0,
offset: 3.0,
interpolation: None,
},
],
};
let keyframes2 = Keyframes {
values: vec![
Keyframe {
id: "4".into(),
value: -100.0,
offset: 0.0,
interpolation: None,
},
Keyframe {
id: "5".into(),
value: 0.0,
offset: 1.0,
interpolation: None,
},
],
};
let rendered_keyframes1: Vec<RenderedKeyframe> = keyframes1
.values
.into_iter()
.enumerate()
.map(|(index, keyframe)| {
let rendered_keyframe = render_keyframe(keyframe, &animation_data, index, 120, 60);
rendered_keyframe
})
.collect();
let rendered_keyframes2: Vec<RenderedKeyframe> = keyframes2
.values
.into_iter()
.enumerate()
.map(|(index, keyframe)| {
let rendered_keyframe = render_keyframe(keyframe, &animation_data, index, 120, 60);
rendered_keyframe
})
.collect();
let val1 = interpolate_rendered_keyframes(
rendered_keyframes1.get(1).unwrap(),
rendered_keyframes1.get(2).unwrap(),
120,
InterpolationType::Linear,
fps,
);
let _val2 = interpolate_rendered_keyframes(
rendered_keyframes2.get(0).unwrap(),
rendered_keyframes2.get(1).unwrap(),
30,
InterpolationType::Linear,
fps,
);
assert_eq!(val1, 200.0);
//println!("{0}", val2);
}
#[test]
fn calculates_the_spring_value() {
let _fps = 60;
let previous_value = 0.0;
let next_value = 500.0;
let mut spring_props = SpringProperties {
mass: 1.0, // Mass of the object attached to the spring
stiffness: 100.0, // Stiffness of the spring
damping: 10.0, // Damping factor of the spring
};
let value1 =
calculate_spring_value(100, previous_value, next_value, 100, 300, &mut spring_props);
let value2 =
calculate_spring_value(150, previous_value, next_value, 100, 300, &mut spring_props);
let value3 =
calculate_spring_value(200, previous_value, next_value, 100, 300, &mut spring_props);
println!("{value1}");
println!("{value2}");
println!("{value3}");
}
#[test]
fn converts_timestamp_to_frame() {
let frame1 = timestamp_to_frame(0.0, 60);
let frame2 = timestamp_to_frame(1.0, 60);
let frame3 = timestamp_to_frame(1.5, 60);
assert_eq!(frame1, 0);
assert_eq!(frame2, 60);
assert_eq!(frame3, 90);
}
#[test]
fn gets_value_at_frame() {
let animation_data = AnimationData {
offset: 0.0,
duration: 5.0,
visible: true,
};
let fps = 60;
let keyframes = Keyframes {
values: vec![
Keyframe {
id: "1".into(),
value: 0.0,
offset: 0.0,
interpolation: None,
},
Keyframe {
id: "2".into(),
value: 100.0,
offset: 1.0,
interpolation: None,
},
Keyframe {
id: "3".into(),
value: 300.0,
offset: 3.0,
interpolation: None,
},
],
};
let value1 = keyframes.get_value_at_frame(50, &animation_data, fps);
let value2 = keyframes.get_value_at_frame(90, &animation_data, fps);
let value3 = keyframes.get_value_at_frame(120, &animation_data, fps);
let value4 = keyframes.get_value_at_frame(180, &animation_data, fps);
let value5 = keyframes.get_value_at_frame(220, &animation_data, fps);
println!("value1: {0}", value1);
println!("value2: {0}", value2);
println!("value3: {0}", value3);
println!("value4: {0}", value4);
println!("value5: {0}", value5);
}

View File

@ -1,64 +0,0 @@
use super::{
entities::common::AnimationData,
values::{AnimatedFloatVec2, AnimatedFloatVec3, AnimatedValue},
};
use crate::animation::timeline::Timeline;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct AnimatedTransform {
pub translate: AnimatedFloatVec2,
pub scale: AnimatedFloatVec2,
pub skew: AnimatedFloatVec2,
pub rotate: AnimatedFloatVec3,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Transform {
pub translate: (f32, f32),
pub scale: (f32, f32),
pub skew: (f32, f32),
pub rotate: (f32, f32, f32),
}
impl AnimatedTransform {
pub fn sort_keyframes(&mut self) {
self.rotate.sort_keyframes();
self.skew.sort_keyframes();
self.scale.sort_keyframes();
self.translate.sort_keyframes();
}
pub fn calculate(&mut self, timeline: &Timeline, animation_data: &AnimationData) -> Transform {
let skew = self.skew.get_value_at_frame(
timeline.render_state.curr_frame,
animation_data,
timeline.fps,
);
let scale = self.scale.get_value_at_frame(
timeline.render_state.curr_frame,
animation_data,
timeline.fps,
);
let translate = self.translate.get_value_at_frame(
timeline.render_state.curr_frame,
animation_data,
timeline.fps,
);
let rotate = self.rotate.get_value_at_frame(
timeline.render_state.curr_frame,
animation_data,
timeline.fps,
);
Transform {
skew,
scale,
translate,
rotate,
}
}
}

View File

@ -1,29 +0,0 @@
use super::{
entities::common::AnimationData,
keyframe::{Keyframe, RenderedKeyframe},
};
pub fn timestamp_to_frame(timestamp: f32, fps: i16) -> i32 {
return (timestamp * fps as f32).round() as i32;
}
pub fn render_keyframe(
keyframe: Keyframe,
animation_data: &AnimationData,
index: usize,
curr_frame: i32,
fps: i16,
) -> RenderedKeyframe {
let animation_start_frame = timestamp_to_frame(animation_data.offset, fps);
let frame_offset = timestamp_to_frame(keyframe.offset, fps);
let absolute_frame = animation_start_frame + frame_offset;
let distance_from_curr = absolute_frame - curr_frame;
RenderedKeyframe {
absolute_frame,
keyframe,
index,
distance_from_curr,
abs_distance_from_curr: distance_from_curr.abs(),
}
}

View File

@ -1,248 +0,0 @@
use super::{
entities::common::AnimationData,
keyframe::{Keyframe, Keyframes},
};
use rayon::prelude::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
pub trait AnimatedValue<T> {
fn sort_keyframes(&mut self);
fn get_value_at_frame(&self, curr_frame: i32, animation_data: &AnimationData, fps: i16) -> T;
fn get_values_at_frame_range(
&self,
start_frame: i32,
end_frame: i32,
animation_data: &AnimationData,
fps: i16,
) -> Vec<T>;
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct AnimatedFloat {
pub keyframes: Keyframes,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct AnimatedFloatVec2 {
pub keyframes: (AnimatedFloat, AnimatedFloat),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct AnimatedFloatVec3 {
pub keyframes: (AnimatedFloat, AnimatedFloat, AnimatedFloat),
}
#[tauri::command]
pub fn get_values_at_frame_range_from_animated_float(
animated_value: AnimatedFloat,
start_frame: i32,
end_frame: i32,
animation_data: AnimationData,
fps: i16,
) -> Vec<f32> {
animated_value.get_values_at_frame_range(start_frame, end_frame, &animation_data, fps)
}
#[tauri::command]
pub fn get_values_at_frame_range_from_animated_float_vec2(
animated_value: AnimatedFloatVec2,
start_frame: i32,
end_frame: i32,
animation_data: AnimationData,
fps: i16,
) -> Vec<(f32, f32)> {
animated_value.get_values_at_frame_range(start_frame, end_frame, &animation_data, fps)
}
#[tauri::command]
pub fn get_values_at_frame_range_from_animated_float_vec3(
animated_value: AnimatedFloatVec3,
start_frame: i32,
end_frame: i32,
animation_data: AnimationData,
fps: i16,
) -> Vec<(f32, f32, f32)> {
animated_value.get_values_at_frame_range(start_frame, end_frame, &animation_data, fps)
}
impl AnimatedFloat {
pub fn new(val: f32) -> AnimatedFloat {
AnimatedFloat {
keyframes: Keyframes {
values: vec![Keyframe {
id: Uuid::new_v4().to_string().into(),
value: val,
offset: 0.0,
interpolation: None,
}],
},
}
}
}
impl AnimatedFloatVec2 {
pub fn new(x: f32, y: f32) -> AnimatedFloatVec2 {
AnimatedFloatVec2 {
keyframes: (AnimatedFloat::new(x), AnimatedFloat::new(y)),
}
}
}
impl AnimatedFloatVec3 {
pub fn new(x: f32, y: f32, z: f32) -> AnimatedFloatVec3 {
AnimatedFloatVec3 {
keyframes: (
AnimatedFloat::new(x),
AnimatedFloat::new(y),
AnimatedFloat::new(z),
),
}
}
}
impl AnimatedValue<f32> for AnimatedFloat {
fn sort_keyframes(&mut self) {
self.keyframes.sort();
}
fn get_value_at_frame(&self, curr_frame: i32, animation_data: &AnimationData, fps: i16) -> f32 {
self.keyframes
.get_value_at_frame(curr_frame, &animation_data, fps)
}
fn get_values_at_frame_range(
&self,
start_frame: i32,
end_frame: i32,
animation_data: &AnimationData,
fps: i16,
) -> Vec<f32> {
let values = (start_frame..end_frame)
.into_par_iter()
.map(|i| self.get_value_at_frame(i, animation_data, fps))
.collect();
values
}
}
impl AnimatedValue<(f32, f32, f32)> for AnimatedFloatVec3 {
fn sort_keyframes(&mut self) {
self.keyframes.0.sort_keyframes();
self.keyframes.1.sort_keyframes();
self.keyframes.2.sort_keyframes();
}
fn get_value_at_frame(
&self,
curr_frame: i32,
animation_data: &AnimationData,
fps: i16,
) -> (f32, f32, f32) {
let x = self
.keyframes
.0
.get_value_at_frame(curr_frame, animation_data, fps);
let y = self
.keyframes
.1
.get_value_at_frame(curr_frame, animation_data, fps);
let z = self
.keyframes
.2
.get_value_at_frame(curr_frame, animation_data, fps);
return (x, y, z);
}
fn get_values_at_frame_range(
&self,
start_frame: i32,
end_frame: i32,
animation_data: &AnimationData,
fps: i16,
) -> Vec<(f32, f32, f32)> {
let x =
self.keyframes
.0
.get_values_at_frame_range(start_frame, end_frame, animation_data, fps);
let y =
self.keyframes
.1
.get_values_at_frame_range(start_frame, end_frame, animation_data, fps);
let z =
self.keyframes
.2
.get_values_at_frame_range(start_frame, end_frame, animation_data, fps);
let vectors: Vec<(f32, f32, f32)> = x
.into_par_iter()
.enumerate()
.map(|(index, val_x)| {
let val_y: f32 = *y.get(index).unwrap();
let val_z: f32 = *z.get(index).unwrap();
(val_x, val_y, val_z)
})
.collect();
vectors
}
}
impl AnimatedValue<(f32, f32)> for AnimatedFloatVec2 {
fn sort_keyframes(&mut self) {
self.keyframes.0.sort_keyframes();
self.keyframes.1.sort_keyframes();
}
fn get_value_at_frame(
&self,
curr_frame: i32,
animation_data: &AnimationData,
fps: i16,
) -> (f32, f32) {
let x = self
.keyframes
.0
.get_value_at_frame(curr_frame, animation_data, fps);
let y = self
.keyframes
.1
.get_value_at_frame(curr_frame, animation_data, fps);
return (x, y);
}
fn get_values_at_frame_range(
&self,
start_frame: i32,
end_frame: i32,
animation_data: &AnimationData,
fps: i16,
) -> Vec<(f32, f32)> {
let x =
self.keyframes
.0
.get_values_at_frame_range(start_frame, end_frame, animation_data, fps);
let y =
self.keyframes
.1
.get_values_at_frame_range(start_frame, end_frame, animation_data, fps);
let vectors: Vec<(f32, f32)> = x
.into_par_iter()
.enumerate()
.map(|(index, val_x)| {
let val_y: f32 = *y.get(index).unwrap();
(val_x, val_y)
})
.collect();
vectors
}
}

View File

@ -1,290 +0,0 @@
use std::str::FromStr;
use crate::animation::primitives::{
interpolations::{EasingFunction, InterpolationType, SpringProperties},
keyframe::{Keyframe, Keyframes},
};
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use super::primitives::{
entities::{
common::{AnimatedEntity, AnimationData, Cache, Entity},
rect::AnimatedRectEntity,
text::AnimatedTextEntity,
},
paint::{Color, FillStyle, Paint, PaintStyle, StrokeStyle, TextAlign, TextPaint},
values::{AnimatedFloat, AnimatedFloatVec2},
};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Input {
pub title: String,
pub sub_title: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Timeline {
entities: Vec<AnimatedEntity>,
pub render_state: RenderState,
pub duration: f32,
pub fps: i16,
pub size: (i32, i32),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RenderState {
pub curr_frame: i32,
}
impl Timeline {
fn calculate(&self) -> Vec<Entity> {
let mut entities = self.entities.clone();
let entities = entities
.par_iter_mut()
.map(|entity| entity.calculate(self))
.filter(|entity| entity.is_some())
.map(|entity| entity.unwrap())
.collect();
return entities;
}
}
fn build_bg(offset: f32, paint: Paint, size: (i32, i32)) -> AnimatedRectEntity {
let bg_box = AnimatedRectEntity {
id: String::from_str("1").unwrap(),
paint,
animation_data: AnimationData {
offset: 0.0 + offset,
duration: 5.0,
visible: true,
},
cache: Cache { valid: false },
transform: None,
origin: AnimatedFloatVec2::new(1280.0 / 2.0, 720.0 / 2.0),
position: AnimatedFloatVec2 {
keyframes: (
AnimatedFloat {
keyframes: Keyframes {
values: vec![
Keyframe {
id: "1".into(),
value: (size.0 * -1) as f32,
offset: 0.0,
interpolation: Some(InterpolationType::EasingFunction(
EasingFunction::QuintOut,
)),
},
Keyframe {
id: "2".into(),
value: 0.0,
offset: 5.0,
interpolation: None,
},
],
},
},
AnimatedFloat {
keyframes: Keyframes {
values: vec![Keyframe {
id: "3".into(),
value: 0.0,
offset: 0.0,
interpolation: None,
}],
},
},
),
},
size: AnimatedFloatVec2 {
keyframes: (
AnimatedFloat {
keyframes: Keyframes {
values: vec![Keyframe {
id: "4".into(),
interpolation: None,
value: size.0 as f32,
offset: 0.0,
}],
},
},
AnimatedFloat {
keyframes: Keyframes {
values: vec![Keyframe {
id: "5".into(),
value: size.1 as f32,
offset: 0.0,
interpolation: None,
}],
},
},
),
},
};
return bg_box;
}
#[tauri::command]
pub fn calculate_timeline_entities_at_frame(timeline: Timeline) -> Vec<Entity> {
timeline.calculate()
}
pub fn test_timeline_entities_at_frame(
render_state: RenderState,
size: (i32, i32),
input: Input,
) -> Vec<Entity> {
let rect1_paint = Paint {
style: PaintStyle::Fill(FillStyle {
color: Color::new(34, 189, 58, 1.0),
}),
};
let rect2_paint = Paint {
style: PaintStyle::Fill(FillStyle {
color: Color::new(23, 178, 28, 1.0),
}),
};
let rect3_paint = Paint {
style: PaintStyle::Fill(FillStyle {
color: Color::new(43, 128, 98, 1.0),
}),
};
let title_paint = TextPaint {
style: PaintStyle::Stroke(StrokeStyle {
color: Color::new(0, 0, 0, 1.0),
width: 10.0,
}),
font_name: "Arial".into(),
align: TextAlign::Center,
size: 20.0,
};
let sub_title_paint = TextPaint {
style: PaintStyle::Fill(FillStyle {
color: Color::new(0, 0, 0, 1.0),
}),
font_name: "Arial".into(),
align: TextAlign::Center,
size: 10.0,
};
let timeline = Timeline {
fps: 60,
duration: 5.0,
size,
entities: vec![
AnimatedEntity::Rect(build_bg(0.0, rect1_paint, size)),
AnimatedEntity::Rect(build_bg(0.5, rect2_paint, size)),
AnimatedEntity::Rect(build_bg(1.0, rect3_paint, size)),
AnimatedEntity::Text(AnimatedTextEntity {
id: String::from_str("2").unwrap(),
paint: title_paint,
cache: Cache { valid: false },
text: input.title,
animation_data: AnimationData {
offset: 0.0,
duration: 6.0,
visible: true,
},
transform: None,
origin: AnimatedFloatVec2 {
keyframes: (
AnimatedFloat {
keyframes: Keyframes {
values: vec![
Keyframe {
id: "1".into(),
value: 0.0,
offset: 0.0,
interpolation: Some(InterpolationType::Spring(
SpringProperties {
mass: 1.0,
damping: 20.0,
stiffness: 200.0,
},
)),
},
Keyframe {
id: "2".into(),
value: (size.0 / 2) as f32,
offset: 2.0,
interpolation: None,
},
],
},
},
AnimatedFloat {
keyframes: Keyframes {
values: vec![Keyframe {
id: "3".into(),
value: (size.1 / 2) as f32,
offset: 0.0,
interpolation: None,
}],
},
},
),
},
}),
AnimatedEntity::Text(AnimatedTextEntity {
id: String::from_str("3").unwrap(),
paint: sub_title_paint,
text: input.sub_title,
cache: Cache { valid: false },
animation_data: AnimationData {
offset: 0.5,
duration: 6.0,
visible: true,
},
transform: None,
origin: AnimatedFloatVec2 {
keyframes: (
AnimatedFloat {
keyframes: Keyframes {
values: vec![
Keyframe {
id: "5".into(),
value: 0.0,
offset: 0.0,
interpolation: Some(InterpolationType::Spring(
SpringProperties {
mass: 1.0,
damping: 20.0,
stiffness: 200.0,
},
)),
},
Keyframe {
id: "6".into(),
value: (size.0 / 2) as f32,
offset: 2.0,
interpolation: None,
},
],
},
},
AnimatedFloat {
keyframes: Keyframes {
values: vec![Keyframe {
id: "7".into(),
value: ((size.1 / 2) as f32) + 80.0,
offset: 0.0,
interpolation: None,
}],
},
},
),
},
}),
],
render_state: render_state,
};
timeline.calculate()
}

View File

@ -1,58 +0,0 @@
use font_kit::source::SystemSource;
#[tauri::command]
pub fn get_system_fonts() -> Option<Vec<String>> {
let source = SystemSource::new();
let found_fonts = source.all_fonts();
match found_fonts {
Ok(found_fonts) => {
let font_names: Vec<String> = found_fonts
.iter()
.map(|f| f.load())
.filter(|f| f.is_ok())
.map(|f| f.unwrap())
.map(|f| f.postscript_name())
.filter(|f| f.is_some())
.map(|f| f.unwrap())
.collect();
Some(font_names)
}
Err(_) => None,
}
}
#[tauri::command]
pub fn get_system_families() -> Option<Vec<String>> {
let source = SystemSource::new();
let found_families = source.all_families();
found_families.ok()
}
#[tauri::command]
pub fn get_system_font(font_name: String) -> Option<Vec<u8>> {
let source = SystemSource::new();
let font = source.select_by_postscript_name(font_name.as_str());
match font {
Ok(font) => {
let font = font.load();
if let Ok(font) = font {
if let Some(font_data) = font.copy_font_data() {
Some(font_data.as_slice().to_owned())
} else {
None
}
} else {
None
}
}
Err(_) => panic!("Err"),
}
}

View File

@ -1,25 +1,27 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!! // Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use crate::{ use creator_core::{
__cmd__calculate_timeline_at_curr_frame, __cmd__get_system_families, __cmd__get_system_font,
__cmd__get_system_fonts, __cmd__get_values_at_frame_range_from_animated_float,
__cmd__get_values_at_frame_range_from_animated_float_vec2,
__cmd__get_values_at_frame_range_from_animated_float_vec3,
animation::{ animation::{
primitives::values::{ primitives::values::animated_values::{
get_values_at_frame_range_from_animated_float, get_values_at_frame_range_from_animated_float,
get_values_at_frame_range_from_animated_float_vec2, get_values_at_frame_range_from_animated_float_vec2,
get_values_at_frame_range_from_animated_float_vec3, get_values_at_frame_range_from_animated_float_vec3,
}, },
timeline::calculate_timeline_entities_at_frame, timeline::calculate_timeline_at_curr_frame,
*,
}, },
fonts::{get_system_families, get_system_font, get_system_fonts}, fonts::fonts::{get_system_families, get_system_font, get_system_fonts},
}; };
pub mod animation;
pub mod fonts;
fn main() { fn main() {
tauri::Builder::default() tauri::Builder::default()
.invoke_handler(tauri::generate_handler![ .invoke_handler(tauri::generate_handler![
calculate_timeline_entities_at_frame, calculate_timeline_at_curr_frame,
get_system_font, get_system_font,
get_system_families, get_system_families,
get_system_fonts, get_system_fonts,

View File

@ -90,7 +90,7 @@ export class Drawer {
const parsedAnimatedEntities = AnimatedEntities.parse(animatedEntities); const parsedAnimatedEntities = AnimatedEntities.parse(animatedEntities);
const data = await invoke("calculate_timeline_entities_at_frame", { const data = await invoke("calculate_timeline_at_curr_frame", {
timeline: { timeline: {
entities: parsedAnimatedEntities, entities: parsedAnimatedEntities,
render_state: renderState, render_state: renderState,

View File

@ -971,6 +971,11 @@
resolved "https://packages.unom.io/@tempblade%2fcommon/-/common-2.0.1.tgz" resolved "https://packages.unom.io/@tempblade%2fcommon/-/common-2.0.1.tgz"
integrity sha512-8uCqsfu2tcQq4O4XODS7Hn7Mj9hZh+Rh+Y0Fsej9Bbemn/WwlIT0WrUSzWGMZLcTspvgl6kz/ljBzCqLAa3Yyw== integrity sha512-8uCqsfu2tcQq4O4XODS7Hn7Mj9hZh+Rh+Y0Fsej9Bbemn/WwlIT0WrUSzWGMZLcTspvgl6kz/ljBzCqLAa3Yyw==
"@types/d3-array@^3.0.5":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.5.tgz#857c1afffd3f51319bbc5b301956aca68acaa7b8"
integrity sha512-Qk7fpJ6qFp+26VeQ47WY0mkwXaiq8+76RJcncDEfMc2ocRzXLO67bLFRNI4OX1aGBoPzsM5Y2T+/m1pldOgD+A==
"@types/d3-color@*": "@types/d3-color@*":
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.0.tgz#6594da178ded6c7c3842f3cc0ac84b156f12f2d4" resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.0.tgz#6594da178ded6c7c3842f3cc0ac84b156f12f2d4"

View File

@ -8,7 +8,7 @@ license = "MIT"
repository = "https://github.com/tempblade/creator" repository = "https://github.com/tempblade/creator"
[lib] [lib]
crate-type = ["cdylib"] crate-type = ["cdylib", "lib"]
[dependencies] [dependencies]
rayon = { version = "1.7", optional = true } rayon = { version = "1.7", optional = true }