Skip to main content

gled_model/asset/scene/
effect.rs

1use crate::{
2    asset::{
3        animation::{Animation, config::AnimationConfig},
4        curve::multiplied_curve::{MultipliedCurve, RangeDegrees, RangePercentage},
5    },
6    asset_id::AssetId,
7    collection::Collections,
8    patching::layout::LayoutSelection,
9    sound::trigger_ref::{CollectSoundTriggers, SoundLevels, SoundTriggerSet},
10};
11use serde::{Deserialize, Serialize};
12
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
14#[serde(default)]
15pub struct Effect {
16    pub color_shift: MultipliedCurve<RangeDegrees>,
17    pub opacity: MultipliedCurve<RangePercentage>,
18    pub beat_progression: MultipliedCurve<RangePercentage>,
19    pub beat_progression_offset: MultipliedCurve<RangePercentage>,
20    /// In 2^n of bpm
21    pub speed_exponent: i32,
22    /// `None` inherits the tile's selection.
23    pub selection: Option<LayoutSelection>,
24    pub animation: Option<AssetId<Animation>>,
25    pub animation_config: AnimationConfig,
26}
27
28impl Eq for Effect {}
29
30impl Default for Effect {
31    fn default() -> Self {
32        Self {
33            color_shift: MultipliedCurve::new_multiplier(0.0),
34            opacity: MultipliedCurve::new_multiplier(1.0),
35            beat_progression: MultipliedCurve::new_curve([
36                0x2E, 0x07, 0x5C, 0xCB, 0x90, 0xC4, 0x47, 0x4B, 0x8D, 0x16, 0xC6, 0x70, 0x40, 0x54,
37                0x99, 0xA6,
38            ]),
39            beat_progression_offset: MultipliedCurve::new_multiplier(0.0),
40            speed_exponent: Default::default(),
41            selection: None,
42            animation: Default::default(),
43            animation_config: Default::default(),
44        }
45    }
46}
47
48/// An effect's values at one moment, with its curves and sound triggers
49/// applied: what the renderer draws it with.
50#[derive(Debug, Clone, Copy, PartialEq, Default)]
51pub struct EffectValues {
52    /// The scene's beat moved by the effect's beat offset; the effect's
53    /// settings are evaluated at it.
54    pub beat: f32,
55    /// The effect's progression curve at `beat`, which drives its animation.
56    pub beat_progression: f32,
57    pub opacity: f32,
58    /// In degrees.
59    pub color_shift: f32,
60}
61
62impl Effect {
63    /// The effect's values at `scene_beat`, the scene's beat position.
64    pub fn values(
65        &self,
66        scene_beat: f32,
67        collections: &Collections,
68        sound: &dyn SoundLevels,
69    ) -> EffectValues {
70        let beat = scene_beat
71            + self
72                .beat_progression_offset
73                .value(scene_beat, collections, sound);
74        EffectValues {
75            beat,
76            beat_progression: self.beat_progression.value(beat, collections, sound),
77            opacity: self.opacity.value(beat, collections, sound),
78            color_shift: self.color_shift.value(beat, collections, sound),
79        }
80    }
81}
82
83impl CollectSoundTriggers for Effect {
84    fn collect_sound_triggers(&self, triggers: &mut SoundTriggerSet) {
85        self.color_shift.collect_sound_triggers(triggers);
86        self.opacity.collect_sound_triggers(triggers);
87        self.beat_progression.collect_sound_triggers(triggers);
88        self.beat_progression_offset
89            .collect_sound_triggers(triggers);
90        self.animation_config.collect_sound_triggers(triggers);
91    }
92}