lumen_engine/
composition.rs1use crate::{audio::AudioTimeline, error::LumenError, graph::Graph};
2
3#[derive(Debug, Clone)]
4pub struct TimelineSettings {
5 pub fps: f32,
6 pub duration_frames: u32,
7}
8
9impl TimelineSettings {
10 pub fn time_seconds(&self, frame: u32) -> f64 {
11 if self.fps <= 0.0 {
12 return 0.0;
13 }
14 frame as f64 / self.fps as f64
15 }
16}
17
18#[derive(Debug, Clone)]
19pub struct RenderSettings {
20 pub width: u32,
21 pub height: u32,
22 pub background_color: [u8; 4],
23}
24
25#[derive(Debug, Clone, Default)]
26pub struct CompositionMetadata {
27 pub name: Option<String>,
28}
29
30#[derive(Debug)]
31pub struct Composition {
32 pub graph: Graph,
33 pub timeline: TimelineSettings,
34 pub render_settings: RenderSettings,
35 pub metadata: Option<CompositionMetadata>,
36 pub audio: Option<AudioTimeline>,
37}
38
39unsafe impl Sync for Composition {}
40unsafe impl Send for Composition {}
41
42impl Composition {
43 pub fn new(graph: Graph, timeline: TimelineSettings, render_settings: RenderSettings) -> Self {
44 Self {
45 graph,
46 timeline,
47 render_settings,
48 metadata: None,
49 audio: None,
50 }
51 }
52
53 pub fn validate_structure(&self) -> Result<(), Vec<LumenError>> {
54 let mut errors = Vec::new();
55
56 match self.graph.validate() {
57 Ok(_) => {}
58 Err(graph_errors) => errors.extend(graph_errors),
59 }
60
61 if errors.is_empty() {
62 Ok(())
63 } else {
64 Err(errors)
65 }
66 }
67}