gled-model 2.32.1

The data model of gled: projects, scenes, effects, animations, curves and assets
Documentation
use super::Scene;
use crate::{
    asset::{
        Asset,
        curve::multiplied_curve::{MultipliedCurve, RangePercentage},
        palette::Palette,
        scene::color::SceneInstanceColor,
    },
    asset_id::AssetId,
    collection::Collections,
    input::event::InputEvent,
    patching::layout::LayoutSelection,
    sound::trigger_ref::{CollectSoundTriggers, SoundLevels, SoundTriggerSet},
};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct SceneInstance {
    #[serde(default = "Uuid::new_v4")]
    pub id: Uuid,
    #[serde(default = "unnamed_scene")]
    pub name: String,

    #[serde(default)]
    pub color: SceneInstanceColor,
    #[serde(default)]
    pub active: bool,
    #[serde(default)]
    pub opacity: MultipliedCurve<RangePercentage>,
    #[serde(default)]
    pub input_dimmer: f32,
    #[serde(default)]
    pub ignore_main_dimmer: bool,
    #[serde(default)]
    pub beat_progression_offset: MultipliedCurve<RangePercentage>,
    #[serde(default)]
    pub activation_input: Option<InputEvent>,
    #[serde(default)]
    pub flash_input: Option<InputEvent>,
    #[serde(default)]
    pub set_offset_on_flash: bool,
    #[serde(default)]
    pub dimmer_input: Option<InputEvent>,
    pub(crate) scene_id: AssetId<Scene>,
    pub scene: Scene,
    /// Which layout and mode this tile drives; effects inherit it.
    #[serde(default)]
    pub selection: LayoutSelection,
    #[serde(default)]
    pub palette_overwrite: Option<Option<Palette>>,

    #[serde(skip)]
    pub flash: bool,
}

fn unnamed_scene() -> String {
    "Unnamed Scene".to_string()
}

impl Clone for SceneInstance {
    fn clone(&self) -> Self {
        Self {
            name: self.name.clone(),
            id: self.id,
            color: self.color,
            active: self.active,
            opacity: self.opacity.clone(),
            input_dimmer: self.input_dimmer,
            ignore_main_dimmer: self.ignore_main_dimmer,
            beat_progression_offset: self.beat_progression_offset.clone(),
            activation_input: self.activation_input,
            flash_input: self.flash_input,
            set_offset_on_flash: self.set_offset_on_flash,
            dimmer_input: self.dimmer_input,
            scene_id: self.scene_id,
            scene: self.scene.clone(),
            selection: self.selection,
            palette_overwrite: self.palette_overwrite.clone(),
            flash: self.flash,
        }
    }
}

impl SceneInstance {
    /// The beat position of the scene's effects: `beat` moved by the
    /// scene's beat offset.
    pub fn scene_beat(&self, beat: f32, collections: &Collections, sound: &dyn SoundLevels) -> f32 {
        beat + self.beat_progression_offset.value(beat, collections, sound)
    }

    pub fn from_scene_id(scene_id: AssetId<Scene>, collections: &Collections) -> Self {
        let asset = Asset::get(scene_id, collections).unwrap_or_default();
        let scene = asset.data.clone();

        Self {
            scene_id,
            scene,
            name: asset
                .path
                .last()
                .map(|s| s.to_string())
                .unwrap_or_else(unnamed_scene),
            color: Default::default(),
            id: Uuid::new_v4(),
            active: Default::default(),
            opacity: MultipliedCurve::new_multiplier(1.0),
            input_dimmer: 1.0,
            ignore_main_dimmer: false,
            beat_progression_offset: MultipliedCurve::new_multiplier(0.0),
            activation_input: Default::default(),
            flash_input: Default::default(),
            set_offset_on_flash: Default::default(),
            dimmer_input: Default::default(),
            flash: Default::default(),
            selection: Default::default(),
            palette_overwrite: Default::default(),
        }
    }

    /// Clone this instance, but assign a fresh `id` so the duplicate is treated
    /// as a distinct instance (e.g. for drag-and-drop and equality checks).
    /// The render thread builds GPU pipelines for the new instance.
    pub fn cloned_with_new_id(&self) -> Self {
        let mut clone = self.clone();
        clone.id = Uuid::new_v4();
        clone
    }
}

impl CollectSoundTriggers for SceneInstance {
    fn collect_sound_triggers(&self, triggers: &mut SoundTriggerSet) {
        self.opacity.collect_sound_triggers(triggers);
        self.beat_progression_offset
            .collect_sound_triggers(triggers);
        self.scene.collect_sound_triggers(triggers);
    }
}