Skip to main content

gled_model/asset/scene/
instance.rs

1use super::Scene;
2use crate::{
3    asset::{
4        Asset,
5        curve::multiplied_curve::{MultipliedCurve, RangePercentage},
6        palette::Palette,
7        scene::color::SceneInstanceColor,
8    },
9    asset_id::AssetId,
10    collection::Collections,
11    input::event::InputEvent,
12    patching::layout::LayoutSelection,
13    sound::trigger_ref::{CollectSoundTriggers, SoundLevels, SoundTriggerSet},
14};
15use serde::{Deserialize, Serialize};
16use uuid::Uuid;
17
18#[derive(Serialize, Deserialize, Debug, PartialEq)]
19pub struct SceneInstance {
20    #[serde(default = "Uuid::new_v4")]
21    pub id: Uuid,
22    #[serde(default = "unnamed_scene")]
23    pub name: String,
24
25    #[serde(default)]
26    pub color: SceneInstanceColor,
27    #[serde(default)]
28    pub active: bool,
29    #[serde(default)]
30    pub opacity: MultipliedCurve<RangePercentage>,
31    #[serde(default)]
32    pub input_dimmer: f32,
33    #[serde(default)]
34    pub ignore_main_dimmer: bool,
35    #[serde(default)]
36    pub beat_progression_offset: MultipliedCurve<RangePercentage>,
37    #[serde(default)]
38    pub activation_input: Option<InputEvent>,
39    #[serde(default)]
40    pub flash_input: Option<InputEvent>,
41    #[serde(default)]
42    pub set_offset_on_flash: bool,
43    #[serde(default)]
44    pub dimmer_input: Option<InputEvent>,
45    pub(crate) scene_id: AssetId<Scene>,
46    pub scene: Scene,
47    /// Which layout and mode this tile drives; effects inherit it.
48    #[serde(default)]
49    pub selection: LayoutSelection,
50    #[serde(default)]
51    pub palette_overwrite: Option<Option<Palette>>,
52
53    #[serde(skip)]
54    pub flash: bool,
55}
56
57fn unnamed_scene() -> String {
58    "Unnamed Scene".to_string()
59}
60
61impl Clone for SceneInstance {
62    fn clone(&self) -> Self {
63        Self {
64            name: self.name.clone(),
65            id: self.id,
66            color: self.color,
67            active: self.active,
68            opacity: self.opacity.clone(),
69            input_dimmer: self.input_dimmer,
70            ignore_main_dimmer: self.ignore_main_dimmer,
71            beat_progression_offset: self.beat_progression_offset.clone(),
72            activation_input: self.activation_input,
73            flash_input: self.flash_input,
74            set_offset_on_flash: self.set_offset_on_flash,
75            dimmer_input: self.dimmer_input,
76            scene_id: self.scene_id,
77            scene: self.scene.clone(),
78            selection: self.selection,
79            palette_overwrite: self.palette_overwrite.clone(),
80            flash: self.flash,
81        }
82    }
83}
84
85impl SceneInstance {
86    /// The beat position of the scene's effects: `beat` moved by the
87    /// scene's beat offset.
88    pub fn scene_beat(&self, beat: f32, collections: &Collections, sound: &dyn SoundLevels) -> f32 {
89        beat + self.beat_progression_offset.value(beat, collections, sound)
90    }
91
92    pub fn from_scene_id(scene_id: AssetId<Scene>, collections: &Collections) -> Self {
93        let asset = Asset::get(scene_id, collections).unwrap_or_default();
94        let scene = asset.data.clone();
95
96        Self {
97            scene_id,
98            scene,
99            name: asset
100                .path
101                .last()
102                .map(|s| s.to_string())
103                .unwrap_or_else(unnamed_scene),
104            color: Default::default(),
105            id: Uuid::new_v4(),
106            active: Default::default(),
107            opacity: MultipliedCurve::new_multiplier(1.0),
108            input_dimmer: 1.0,
109            ignore_main_dimmer: false,
110            beat_progression_offset: MultipliedCurve::new_multiplier(0.0),
111            activation_input: Default::default(),
112            flash_input: Default::default(),
113            set_offset_on_flash: Default::default(),
114            dimmer_input: Default::default(),
115            flash: Default::default(),
116            selection: Default::default(),
117            palette_overwrite: Default::default(),
118        }
119    }
120
121    /// Clone this instance, but assign a fresh `id` so the duplicate is treated
122    /// as a distinct instance (e.g. for drag-and-drop and equality checks).
123    /// The render thread builds GPU pipelines for the new instance.
124    pub fn cloned_with_new_id(&self) -> Self {
125        let mut clone = self.clone();
126        clone.id = Uuid::new_v4();
127        clone
128    }
129}
130
131impl CollectSoundTriggers for SceneInstance {
132    fn collect_sound_triggers(&self, triggers: &mut SoundTriggerSet) {
133        self.opacity.collect_sound_triggers(triggers);
134        self.beat_progression_offset
135            .collect_sound_triggers(triggers);
136        self.scene.collect_sound_triggers(triggers);
137    }
138}