diff options
| author | cashmere <cashmere@autistici.org> | 2026-07-28 20:14:51 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-07-28 20:14:51 +0200 |
| commit | 32438ce25f69de99d2523b98237f62cfa90890d7 (patch) | |
| tree | 3a712c347dec0889bdea3328b4c817c2d9392b27 /rust/crates/scene/src/factory.rs | |
| parent | f5a82152394fde4d8f740f664ab7737b82861618 (diff) | |
| download | opencut-32438ce25f69de99d2523b98237f62cfa90890d7.tar.gz | |
feat: port domain crates to Rust (session 1 complete)
All green: cargo test --workspace (~300 tests, 0 failures).
- timeline (45): placement, resize/ripple, split, snap, retime,
audio separation, scene helpers
- animation (73): bezier solver, channel sampling, keyframe ops,
split/clamp/clone, param definitions
- commands (9): Command trait, BatchCommand, history, 19 concrete
commands, freeze-frame port 1:1
- audio (22): audible collection, range mixing, mastering limiter,
rms/peak buckets
- text (19): cosmic-text layout/measure/raster, backgrounds,
decorations
- graphics (52): full CSS gradient parser, tiny-skia raster,
4 shape definitions
- effect-defs (16): blur definition, registry, pass resolution
- mask-defs (19): all 9 mask renderers via tiny-skia
- renderer (6): node model + scene builder port
- desktop: GPUI projects screen wired to ProjectStore
- scene: factory (web defaults: v32, Main Track, 1920x1080, 30fps)
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); + } +} |
