gled-model 2.31.2

The data model of gled: projects, scenes, effects, animations, curves and assets
Documentation
use super::Curve;
use crate::{
    asset::Asset,
    asset_id::AssetId,
    collection::Collections,
    sound::trigger_ref::{CollectSoundTriggers, SoundLevels, SoundTriggerRef, SoundTriggerSet},
};
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use uuid::Uuid;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct MultipliedCurve<R> {
    #[serde(default = "default_multiplier")]
    pub multiplier: f32,
    pub curve: Option<AssetId<Curve>>,
    #[serde(default)]
    pub sound_trigger: Option<SoundTriggerRef>,
    #[serde(skip)]
    _phantom: PhantomData<R>,
}

fn default_multiplier() -> f32 {
    1.0
}

impl<R> MultipliedCurve<R> {
    pub const fn new_multiplier(multiplier: f32) -> Self {
        Self {
            multiplier,
            curve: None,
            sound_trigger: None,
            _phantom: PhantomData,
        }
    }

    pub fn set_multiplier(&mut self, multiplier: f32) {
        self.multiplier = multiplier;
    }

    pub fn set_curve(&mut self, curve: Option<AssetId<Curve>>) {
        self.curve = curve;
    }

    pub(crate) const fn new_curve(bytes: [u8; 16]) -> Self {
        Self {
            multiplier: 1.0,
            curve: Some(AssetId::from_uuid(Uuid::from_bytes(bytes))),
            sound_trigger: None,
            _phantom: PhantomData,
        }
    }

    pub fn sound_trigger_value(&self, sound_data: &dyn SoundLevels) -> f32 {
        self.sound_trigger
            .as_ref()
            .map(|trigger| sound_data.level(&trigger.id))
            .unwrap_or(1.0)
    }

    /// The curve at this beat, 1 without a curve.
    pub fn curve_preview_value(&self, beat_progression: f32, collections: &Collections) -> f32 {
        self.curve
            .and_then(|id| Asset::get(id, collections))
            .map(|curve| curve.data.value(beat_progression % 4.0))
            .unwrap_or(1.0)
    }
}

impl<R> CollectSoundTriggers for MultipliedCurve<R> {
    fn collect_sound_triggers(&self, triggers: &mut SoundTriggerSet) {
        self.sound_trigger.collect_sound_triggers(triggers);
    }
}

#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash)]
pub struct RangePercentage;

#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash)]
pub struct RangeDegrees;

impl<R> Default for MultipliedCurve<R> {
    fn default() -> Self {
        Self::new_multiplier(default_multiplier())
    }
}

impl<R> Eq for MultipliedCurve<R> {}

impl<R> PartialEq for MultipliedCurve<R> {
    fn eq(&self, other: &Self) -> bool {
        self.multiplier == other.multiplier
            && self.curve == other.curve
            && self.sound_trigger == other.sound_trigger
    }
}

impl MultipliedCurve<RangePercentage> {
    pub fn value(
        &self,
        beat_progression: f32,
        collections: &Collections,
        sound_data: &dyn SoundLevels,
    ) -> f32 {
        self.curve_preview_value(beat_progression, collections)
            * self.multiplier
            * self.sound_trigger_value(sound_data)
    }
}

impl MultipliedCurve<RangeDegrees> {
    pub fn value(
        &self,
        beat_progression: f32,
        collections: &Collections,
        sound_data: &dyn SoundLevels,
    ) -> f32 {
        self.curve_preview_value(beat_progression, collections)
            * self.multiplier
            * 360.0
            * self.sound_trigger_value(sound_data)
    }
}