diff --git a/app/package.json b/app/package.json index 58938d6..d3e6694 100644 --- a/app/package.json +++ b/app/package.json @@ -22,6 +22,7 @@ "@radix-ui/react-toolbar": "^1.0.3", "@tauri-apps/api": "^1.3.0", "@tempblade/common": "^2.0.1", + "@types/d3-array": "^3.0.5", "@types/lodash.set": "^4.3.7", "@unom/style": "^0.2.14", "@visx/axis": "^3.1.0", diff --git a/app/src-tauri/Cargo.lock b/app/src-tauri/Cargo.lock index bcc34ee..8e3fb19 100644 --- a/app/src-tauri/Cargo.lock +++ b/app/src-tauri/Cargo.lock @@ -418,6 +418,20 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "creator_rs" +version = "0.1.0" +dependencies = [ + "font-kit", + "rayon", + "serde", + "serde_json", + "simple-easing", + "tauri", + "uuid", + "wasm-bindgen", +] + [[package]] name = "crossbeam-channel" version = "0.5.8" @@ -441,14 +455,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "memoffset", + "memoffset 0.9.0", "scopeguard", ] @@ -645,9 +659,9 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "dlib" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ "libloading", ] @@ -764,7 +778,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535" dependencies = [ - "memoffset", + "memoffset 0.8.0", "rustc_version 0.4.0", ] @@ -1081,8 +1095,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1547,12 +1563,12 @@ checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" dependencies = [ "cfg-if", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1694,6 +1710,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -1966,9 +1991,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70" +checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9" dependencies = [ "thiserror", "ucd-trie", @@ -2570,11 +2595,11 @@ dependencies = [ [[package]] name = "serde_with" -version = "2.3.3" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +checksum = "9f02d8aa6e3c385bf084924f660ce2a3a6bd333ba55b35e8590b321f35d88513" dependencies = [ - "base64 0.13.1", + "base64 0.21.0", "chrono", "hex", "indexmap", @@ -2586,9 +2611,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "2.3.3" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" +checksum = "edc7d5d3932fb12ce722ee5e64dd38c504efba37567f0c402f6ca728c3b8b070" dependencies = [ "darling", "proc-macro2", @@ -2881,9 +2906,9 @@ checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5" [[package]] name = "tauri" -version = "1.3.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d42ba3a2e8556722f31336a0750c10dbb6a81396a1c452977f515da83f69f842" +checksum = "7fbe522898e35407a8e60dc3870f7579fea2fc262a6a6072eccdd37ae1e1d91e" dependencies = [ "anyhow", "cocoa", @@ -2929,9 +2954,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "929b3bd1248afc07b63e33a6a53c3f82c32d0b0a5e216e4530e94c467e019389" +checksum = "7d2edd6a259b5591c8efdeb9d5702cb53515b82a6affebd55c7fd6d3a27b7d1b" dependencies = [ "anyhow", "cargo_toml", @@ -2942,14 +2967,13 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", - "winnow", ] [[package]] name = "tauri-codegen" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a2105f807c6f50b2fa2ce5abd62ef207bc6f14c9fcc6b8caec437f6fb13bde" +checksum = "54ad2d49fdeab4a08717f5b49a163bdc72efc3b1950b6758245fcde79b645e1a" dependencies = [ "base64 0.21.0", "brotli", @@ -2973,9 +2997,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8784cfe6f5444097e93c69107d1ac5e8f13d02850efa8d8f2a40fe79674cef46" +checksum = "8eb12a2454e747896929338d93b0642144bb51e0dddbb36e579035731f0d76b7" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -2987,9 +3011,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b80ea3fcd5fefb60739a3b577b277e8fc30434538a2f5bba82ad7d4368c422" +checksum = "108683199cb18f96d2d4134187bb789964143c845d2d154848dda209191fd769" dependencies = [ "gtk", "http", @@ -3008,9 +3032,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1c396950b1ba06aee1b4ffe6c7cd305ff433ca0e30acbc5fa1a2f92a4ce70f1" +checksum = "0b7aa256a1407a3a091b5d843eccc1a5042289baf0a43d1179d9f0fcfea37c1b" dependencies = [ "cocoa", "gtk", @@ -3028,12 +3052,13 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6f9c2dafef5cbcf52926af57ce9561bd33bb41d7394f8bb849c0330260d864" +checksum = "03fc02bb6072bb397e1d473c6f76c953cda48b4a2d0cce605df284aa74a12e84" dependencies = [ "brotli", "ctor", + "dunce", "glob", "heck 0.4.1", "html5ever", @@ -3068,16 +3093,13 @@ dependencies = [ name = "tempblade-creator-app" version = "0.0.0" dependencies = [ - "font-kit", + "creator_rs", "logging_timer", - "rayon", "serde", "serde_json", - "simple-easing", "tauri", "tauri-build", "tint", - "uuid", ] [[package]] @@ -3382,15 +3404,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" dependencies = [ "getrandom 0.2.9", - "rand 0.8.5", "uuid-macro-internal", + "wasm-bindgen", ] [[package]] name = "uuid-macro-internal" -version = "1.3.3" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f67b459f42af2e6e1ee213cb9da4dbd022d3320788c3fb3e1b893093f1e45da" +checksum = "8614dda80b9075fbca36bc31b58d1447715b1236af98dee21db521c47a0cc2c0" dependencies = [ "proc-macro2", "quote", diff --git a/app/src-tauri/Cargo.toml b/app/src-tauri/Cargo.toml index 490a266..e5a71f2 100644 --- a/app/src-tauri/Cargo.toml +++ b/app/src-tauri/Cargo.toml @@ -10,20 +10,20 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] -tauri-build = { version = "1.3", features = [] } +tauri-build = { version = "1.4", features = [] } [dependencies] - -uuid = { version = "1.3.3", features = ["v4", "fast-rng", "macro-diagnostics"] } -tauri = { version = "1.3", features = ["dialog-open", "dialog-save", "shell-open"] } +creator_core = { path = "../../lib/creator_rs", features = [ + "fonts", + "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_json = "1.0" tint = "1.0.0" -simple-easing = "1.0.1" logging_timer = "1.1.0" -rayon = "1.7" -font-kit = "0.11.0" [features] # this feature is used for production builds or when `devPath` points to the filesystem diff --git a/app/src-tauri/src/animation/mod.rs b/app/src-tauri/src/animation/mod.rs deleted file mode 100644 index 818b3eb..0000000 --- a/app/src-tauri/src/animation/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod primitives; -pub mod timeline; diff --git a/app/src-tauri/src/animation/primitives/circular_text.rs b/app/src-tauri/src/animation/primitives/circular_text.rs deleted file mode 100644 index 17081ee..0000000 --- a/app/src-tauri/src/animation/primitives/circular_text.rs +++ /dev/null @@ -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(); - } -} diff --git a/app/src-tauri/src/animation/primitives/entities/common.rs b/app/src-tauri/src/animation/primitives/entities/common.rs deleted file mode 100644 index 4dadd90..0000000 --- a/app/src-tauri/src/animation/primitives/entities/common.rs +++ /dev/null @@ -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; -} - -#[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 { - 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, -} diff --git a/app/src-tauri/src/animation/primitives/entities/ellipse.rs b/app/src-tauri/src/animation/primitives/entities/ellipse.rs deleted file mode 100644 index a200041..0000000 --- a/app/src-tauri/src/animation/primitives/entities/ellipse.rs +++ /dev/null @@ -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, -} - -#[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, -} - -impl Drawable for AnimatedEllipseEntity {} -impl Animateable for AnimatedEllipseEntity { - fn calculate(&mut self, timeline: &Timeline) -> Option { - 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 = 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(); - } -} diff --git a/app/src-tauri/src/animation/primitives/entities/mod.rs b/app/src-tauri/src/animation/primitives/entities/mod.rs deleted file mode 100644 index d5ca160..0000000 --- a/app/src-tauri/src/animation/primitives/entities/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod common; -pub mod ellipse; -pub mod rect; -pub mod staggered_text; -pub mod text; diff --git a/app/src-tauri/src/animation/primitives/entities/rect.rs b/app/src-tauri/src/animation/primitives/entities/rect.rs deleted file mode 100644 index 167c8ee..0000000 --- a/app/src-tauri/src/animation/primitives/entities/rect.rs +++ /dev/null @@ -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, -} - -#[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, -} - -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 { - 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 = 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 - } - } -} diff --git a/app/src-tauri/src/animation/primitives/entities/staggered_text.rs b/app/src-tauri/src/animation/primitives/entities/staggered_text.rs deleted file mode 100644 index fd6b7a6..0000000 --- a/app/src-tauri/src/animation/primitives/entities/staggered_text.rs +++ /dev/null @@ -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, - pub paint: TextPaint, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct StaggeredTextLetter { - pub transform: Option>, - 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, - 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, - pub animation_data: AnimationData, - pub letter: StaggeredTextLetter, -} - -impl Drawable for AnimatedStaggeredTextEntity {} -impl Animateable for AnimatedStaggeredTextEntity { - fn calculate(&mut self, timeline: &Timeline) -> Option { - let should_draw: bool = self.should_draw(&self.animation_data, timeline); - - if should_draw { - self.sort_keyframes(); - - let transform: Option = 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> = match self.letter.transform.clone() { - Some(mut val) => { - let mut transforms: Vec = 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(); - } - } -} diff --git a/app/src-tauri/src/animation/primitives/entities/text.rs b/app/src-tauri/src/animation/primitives/entities/text.rs deleted file mode 100644 index 15969d5..0000000 --- a/app/src-tauri/src/animation/primitives/entities/text.rs +++ /dev/null @@ -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, -} - -#[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, -} - -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 = 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 { - 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(); - } -} diff --git a/app/src-tauri/src/animation/primitives/interpolations.rs b/app/src-tauri/src/animation/primitives/interpolations.rs deleted file mode 100644 index 6055b14..0000000 --- a/app/src-tauri/src/animation/primitives/interpolations.rs +++ /dev/null @@ -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; - } - }; -} diff --git a/app/src-tauri/src/animation/primitives/keyframe.rs b/app/src-tauri/src/animation/primitives/keyframe.rs deleted file mode 100644 index d9cf43c..0000000 --- a/app/src-tauri/src/animation/primitives/keyframe.rs +++ /dev/null @@ -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, - pub interpolation: Option, -} - -impl Keyframe { - pub fn new( - value: f32, - offset: f32, - id: Arc, - interpolation: Option, - ) -> 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, -} - -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 = 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)); - } -} diff --git a/app/src-tauri/src/animation/primitives/mod.rs b/app/src-tauri/src/animation/primitives/mod.rs deleted file mode 100644 index f047a2f..0000000 --- a/app/src-tauri/src/animation/primitives/mod.rs +++ /dev/null @@ -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; diff --git a/app/src-tauri/src/animation/primitives/paint.rs b/app/src-tauri/src/animation/primitives/paint.rs deleted file mode 100644 index 695c5af..0000000 --- a/app/src-tauri/src/animation/primitives/paint.rs +++ /dev/null @@ -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, -} diff --git a/app/src-tauri/src/animation/primitives/tests.rs b/app/src-tauri/src/animation/primitives/tests.rs deleted file mode 100644 index 1c2957d..0000000 --- a/app/src-tauri/src/animation/primitives/tests.rs +++ /dev/null @@ -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 = 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 = 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); -} diff --git a/app/src-tauri/src/animation/primitives/transform.rs b/app/src-tauri/src/animation/primitives/transform.rs deleted file mode 100644 index 2416245..0000000 --- a/app/src-tauri/src/animation/primitives/transform.rs +++ /dev/null @@ -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, - } - } -} diff --git a/app/src-tauri/src/animation/primitives/utils.rs b/app/src-tauri/src/animation/primitives/utils.rs deleted file mode 100644 index 5cc0afe..0000000 --- a/app/src-tauri/src/animation/primitives/utils.rs +++ /dev/null @@ -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(), - } -} diff --git a/app/src-tauri/src/animation/primitives/values.rs b/app/src-tauri/src/animation/primitives/values.rs deleted file mode 100644 index 3bb10c5..0000000 --- a/app/src-tauri/src/animation/primitives/values.rs +++ /dev/null @@ -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 { - 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; -} -#[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 { - 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 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 { - 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 - } -} diff --git a/app/src-tauri/src/animation/timeline.rs b/app/src-tauri/src/animation/timeline.rs deleted file mode 100644 index 5f3dfe0..0000000 --- a/app/src-tauri/src/animation/timeline.rs +++ /dev/null @@ -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, - 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 { - 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 { - timeline.calculate() -} - -pub fn test_timeline_entities_at_frame( - render_state: RenderState, - size: (i32, i32), - input: Input, -) -> Vec { - 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() -} diff --git a/app/src-tauri/src/fonts.rs b/app/src-tauri/src/fonts.rs deleted file mode 100644 index c4c32be..0000000 --- a/app/src-tauri/src/fonts.rs +++ /dev/null @@ -1,58 +0,0 @@ -use font_kit::source::SystemSource; - -#[tauri::command] -pub fn get_system_fonts() -> Option> { - let source = SystemSource::new(); - - let found_fonts = source.all_fonts(); - - match found_fonts { - Ok(found_fonts) => { - let font_names: Vec = 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> { - let source = SystemSource::new(); - - let found_families = source.all_families(); - - found_families.ok() -} - -#[tauri::command] -pub fn get_system_font(font_name: String) -> Option> { - 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"), - } -} diff --git a/app/src-tauri/src/main.rs b/app/src-tauri/src/main.rs index 981fd87..8086c5c 100644 --- a/app/src-tauri/src/main.rs +++ b/app/src-tauri/src/main.rs @@ -1,25 +1,27 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![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::{ - primitives::values::{ + primitives::values::animated_values::{ 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_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() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![ - calculate_timeline_entities_at_frame, + calculate_timeline_at_curr_frame, get_system_font, get_system_families, get_system_fonts, diff --git a/app/src/components/Timeline/TrackDisplay/TrackDisplayType.tsx b/app/src/components/Timeline/TrackDisplay/TrackDisplayType.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/drawers/draw.ts b/app/src/drawers/draw.ts index 743c3a2..aaf724b 100644 --- a/app/src/drawers/draw.ts +++ b/app/src/drawers/draw.ts @@ -90,7 +90,7 @@ export class Drawer { const parsedAnimatedEntities = AnimatedEntities.parse(animatedEntities); - const data = await invoke("calculate_timeline_entities_at_frame", { + const data = await invoke("calculate_timeline_at_curr_frame", { timeline: { entities: parsedAnimatedEntities, render_state: renderState, diff --git a/app/src/drawers/effect-layer.ts b/app/src/drawers/effect-layer.ts deleted file mode 100644 index e69de29..0000000 diff --git a/app/yarn.lock b/app/yarn.lock index cf74618..ca1c2d1 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -971,6 +971,11 @@ resolved "https://packages.unom.io/@tempblade%2fcommon/-/common-2.0.1.tgz" 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@*": version "3.1.0" resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.0.tgz#6594da178ded6c7c3842f3cc0ac84b156f12f2d4" diff --git a/lib/creator_rs/Cargo.toml b/lib/creator_rs/Cargo.toml index ea8207b..aae8b3c 100644 --- a/lib/creator_rs/Cargo.toml +++ b/lib/creator_rs/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT" repository = "https://github.com/tempblade/creator" [lib] -crate-type = ["cdylib"] +crate-type = ["cdylib", "lib"] [dependencies] rayon = { version = "1.7", optional = true }