gled-model 2.34.0

The data model of gled: projects, scenes, effects, animations, curves and assets
Documentation
use crate::{
    asset::curve::multiplied_curve::{MultipliedCurve, RangeDegrees, RangePercentage},
    collection::Collections,
    sound::trigger_ref::{CollectSoundTriggers, SoundLevels, SoundTriggerSet},
};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum FloatValue {
    F32(f32),
    Percentage(MultipliedCurve<RangePercentage>),
    Degrees(MultipliedCurve<RangeDegrees>),
}

impl Eq for FloatValue {}

impl Default for FloatValue {
    fn default() -> Self {
        Self::F32(0.0)
    }
}

impl FloatValue {
    pub fn percentage(&mut self) -> &mut MultipliedCurve<RangePercentage> {
        match self {
            Self::Percentage(value) => value,
            _ => {
                *self = Self::Percentage(Default::default());
                if let Self::Percentage(value) = self {
                    value
                } else {
                    unreachable!()
                }
            }
        }
    }

    pub fn degrees(&mut self) -> &mut MultipliedCurve<RangeDegrees> {
        match self {
            Self::Degrees(value) => value,
            _ => {
                *self = Self::Degrees(Default::default());
                if let Self::Degrees(value) = self {
                    value
                } else {
                    unreachable!()
                }
            }
        }
    }

    pub(crate) fn value(
        &self,
        beat_progression: f32,
        collection: &Collections,
        sound_data: &dyn SoundLevels,
    ) -> f32 {
        match self {
            Self::F32(value) => *value,
            Self::Percentage(value) => value.value(beat_progression, collection, sound_data),
            Self::Degrees(value) => value.value(beat_progression, collection, sound_data),
        }
    }

    /// The value as a share of its range: degrees over a full turn, the
    /// others as they are.
    pub fn normalized_value(
        &self,
        beat_progression: f32,
        collection: &Collections,
        sound_data: &dyn SoundLevels,
    ) -> f32 {
        match self {
            Self::Degrees(_) => self.value(beat_progression, collection, sound_data) / 360.0,
            Self::F32(_) | Self::Percentage(_) => {
                self.value(beat_progression, collection, sound_data)
            }
        }
    }

    /// The setting's own value: the number of a plain value, the multiplier
    /// of a curve. A controller's fader sets and shows this.
    pub fn multiplier(&self) -> f32 {
        match self {
            Self::F32(value) => *value,
            Self::Percentage(curve) => curve.multiplier,
            Self::Degrees(curve) => curve.multiplier,
        }
    }

    /// Sets what `multiplier` returns, keeping a curve and its sound trigger.
    pub fn set_multiplier(&mut self, multiplier: f32) {
        match self {
            Self::F32(value) => *value = multiplier,
            Self::Percentage(curve) => curve.set_multiplier(multiplier),
            Self::Degrees(curve) => curve.set_multiplier(multiplier),
        }
    }
}

impl CollectSoundTriggers for FloatValue {
    fn collect_sound_triggers(&self, triggers: &mut SoundTriggerSet) {
        match self {
            Self::F32(_) => {}
            Self::Percentage(value) => value.collect_sound_triggers(triggers),
            Self::Degrees(value) => value.collect_sound_triggers(triggers),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::asset_id::AssetId;

    /// A controller's fader sets the multiplier; the curve the setting
    /// follows must stay.
    #[test]
    fn setting_the_multiplier_keeps_the_curve() {
        let curve = Some(AssetId::default());
        let mut inner = MultipliedCurve::new_multiplier(1.0);
        inner.set_curve(curve);
        let mut value = FloatValue::Percentage(inner);
        value.set_multiplier(0.25);
        assert_eq!(value.multiplier(), 0.25);
        assert!(matches!(value, FloatValue::Percentage(ref inner) if inner.curve == curve));
    }

    #[test]
    fn a_plain_value_is_its_own_multiplier() {
        let mut value = FloatValue::F32(0.5);
        value.set_multiplier(0.75);
        assert_eq!(value, FloatValue::F32(0.75));
    }
}