diff options
Diffstat (limited to 'rust/crates/scene/src/factory.rs')
| -rw-r--r-- | rust/crates/scene/src/factory.rs | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/rust/crates/scene/src/factory.rs b/rust/crates/scene/src/factory.rs new file mode 100644 index 00000000..d9a8e8a0 --- /dev/null +++ b/rust/crates/scene/src/factory.rs @@ -0,0 +1,113 @@ +use chrono::{DateTime, TimeZone, Utc}; +use time::{FrameRate, MediaTime}; +use uuid::Uuid; + +use crate::project::{ + Background, CanvasSize, CanvasSizeMode, Project, ProjectMetadata, ProjectSettings, +}; +use crate::scene::Scene; +use crate::track::{SceneTracks, Track}; + +pub const MAIN_TRACK_NAME: &str = "Main Track"; +pub const CURRENT_PROJECT_VERSION: u32 = 32; +pub const DEFAULT_BACKGROUND_COLOR: &str = "#000000"; +pub const DEFAULT_CANVAS_SIZE: CanvasSize = CanvasSize { + width: 1920, + height: 1080, +}; +pub const DEFAULT_FPS: FrameRate = FrameRate { + numerator: 30, + denominator: 1, +}; + +pub fn generate_id() -> String { + Uuid::new_v4().to_string() +} + +fn now_millis() -> DateTime<Utc> { + Utc.timestamp_millis_opt(Utc::now().timestamp_millis()).unwrap() +} + +pub fn build_default_scene(name: impl Into<String>, is_main: bool) -> Scene { + let now = now_millis(); + Scene { + id: generate_id(), + name: name.into(), + is_main, + tracks: SceneTracks { + overlay: Vec::new(), + main: Track::Video { + id: generate_id(), + name: MAIN_TRACK_NAME.to_string(), + elements: Vec::new(), + muted: false, + hidden: false, + }, + audio: Vec::new(), + }, + bookmarks: Vec::new(), + created_at: now, + updated_at: now, + } +} + +pub fn new_project(name: impl Into<String>) -> Project { + let main_scene = build_default_scene("Main scene", true); + let now = now_millis(); + Project { + metadata: ProjectMetadata { + id: generate_id(), + name: name.into(), + thumbnail: None, + duration: MediaTime::ZERO, + created_at: now, + updated_at: now, + }, + current_scene_id: main_scene.id.clone(), + scenes: vec![main_scene], + settings: ProjectSettings { + fps: DEFAULT_FPS, + canvas_size: DEFAULT_CANVAS_SIZE, + canvas_size_mode: Some(CanvasSizeMode::Preset), + last_custom_canvas_size: None, + original_canvas_size: None, + background: Background::Color { + color: DEFAULT_BACKGROUND_COLOR.to_string(), + }, + }, + version: CURRENT_PROJECT_VERSION, + timeline_view_state: None, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn new_project_matches_web_defaults() { + let project = new_project("Untitled Project"); + assert_eq!(project.version, 32); + assert_eq!(project.scenes.len(), 1); + assert!(project.scenes[0].is_main); + assert_eq!(project.current_scene_id, project.scenes[0].id); + assert_eq!(project.settings.canvas_size.width, 1920); + assert_eq!(project.settings.fps.numerator, 30); + match &project.scenes[0].tracks.main { + Track::Video { name, .. } => assert_eq!(name, "Main Track"), + _ => panic!("main track must be video"), + } + match &project.settings.background { + Background::Color { color } => assert_eq!(color, "#000000"), + _ => panic!("default background must be color"), + } + } + + #[test] + fn new_project_round_trips_through_json() { + let project = new_project("Test"); + let json = serde_json::to_value(&project).unwrap(); + let parsed: Project = serde_json::from_value(json).unwrap(); + assert_eq!(parsed, project); + } +} |
