gled-core 2.30.2

The engine of gled without a user interface: inputs, timing, rendering, Art-Net/DMX output and storage
Documentation
//! The lamp layout of the project's SVG, parsed by the engine whenever the
//! SVG changes, so outputs work without a window that draws it.

use std::sync::Arc;

use crate::{
    pipeline::extract_output::OutputConfig,
    runtime::svg::{apply_svg_layout, reset_svg_layout},
    storage::asset::svg::Svg,
};

#[derive(Debug, Default)]
pub(crate) struct SvgLayout {
    /// The contents the current layout was parsed from.
    parsed: Option<Arc<str>>,
    /// Counts the layouts applied, so interfaces notice a new one.
    generation: u64,
}

impl SvgLayout {
    /// Parses `svg` if it differs from the one parsed last, or clears the
    /// layout without one. Returns whether the lamp positions changed.
    pub(crate) fn update(&mut self, svg: Option<&Svg>, output_config: &mut OutputConfig) -> bool {
        let contents = svg.map(Svg::contents);
        let current = match (&self.parsed, contents) {
            (Some(parsed), Some(contents)) => Arc::ptr_eq(parsed, contents) || parsed == contents,
            (None, None) => true,
            _ => false,
        };
        if current {
            return false;
        }

        self.parsed = contents.cloned();
        self.generation += 1;
        match contents {
            Some(contents) => {
                apply_svg_layout(contents, output_config);
            }
            None => reset_svg_layout(),
        }
        true
    }

    /// Forgets the parsed SVG, so the next `update` parses again.
    pub(crate) fn reset(&mut self) {
        self.parsed = None;
        self.generation += 1;
        reset_svg_layout();
    }

    pub(crate) fn generation(&self) -> u64 {
        self.generation
    }
}