gled-core 2.31.2

The engine of gled without a user interface: inputs, timing, rendering, Art-Net/DMX output and storage
Documentation
//! Actions on the effects of a scene instance.

use std::sync::Arc;

use gled_model::patching::layout::LayoutSelection;

use crate::action::{UiAction, scene_effect_by_target, scene_instance_by_target};
use crate::engine::Engine;
use crate::storage::asset::{
    animation::config::float_value::FloatValue, curve::multiplied_curve::MultipliedCurve,
};

use super::ignore_without_project;

impl Engine {
    /// Adds, removes and edits the effects of a scene instance.
    pub(super) fn apply_effect_action(&mut self, action: UiAction) {
        match (self.project.as_mut().map(Arc::make_mut), action) {
            (Some(project), UiAction::SetSceneEffectOpacity(target, effect_index, opacity)) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.opacity = MultipliedCurve::new_multiplier(opacity);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectOpacityMultiplier(target, effect_index, value),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.opacity.set_multiplier(value);
                }
            }
            (Some(project), UiAction::SetSceneEffectOpacityCurve(target, effect_index, curve)) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.opacity.set_curve(curve);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectColorShift(target, effect_index, color_shift),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.color_shift = MultipliedCurve::new_multiplier(color_shift);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectColorShiftMultiplier(target, effect_index, value),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.color_shift.set_multiplier(value);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectColorShiftCurve(target, effect_index, curve),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.color_shift.set_curve(curve);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectBeatProgression(target, effect_index, beat_progression),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.beat_progression = MultipliedCurve::new_multiplier(beat_progression);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectBeatProgressionMultiplier(target, effect_index, value),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.beat_progression.set_multiplier(value);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectBeatProgressionCurve(target, effect_index, curve),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.beat_progression.set_curve(curve);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectBeatOffset(target, effect_index, beat_offset),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.beat_progression_offset = MultipliedCurve::new_multiplier(beat_offset);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectBeatOffsetMultiplier(target, effect_index, value),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.beat_progression_offset.set_multiplier(value);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectBeatOffsetCurve(target, effect_index, curve),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.beat_progression_offset.set_curve(curve);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectSpeedExponent(target, effect_index, speed_exponent),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.speed_exponent = speed_exponent;
                }
            }
            (Some(project), UiAction::SetSceneEffectLayout(target, effect_index, stack_index)) => {
                // `None` inherits the tile's layout; an index past the
                // stack leaves the effect as it is.
                let layout = match stack_index {
                    None => None,
                    Some(index) => {
                        let Some(layout) = project.patch.layout_refs().get(index).copied() else {
                            tracing::debug!(
                                index,
                                "No layout at this stack index, the effect keeps its own"
                            );
                            return;
                        };
                        Some(layout)
                    }
                };
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    // The same layout again keeps the mode chosen for it.
                    effect.selection = layout.map(|layout| match effect.selection {
                        Some(current) if current.layout == layout => current,
                        _ => LayoutSelection::new(layout, 0),
                    });
                }
            }
            (Some(project), UiAction::SetSceneEffectAnimation(target, effect_index, animation)) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) {
                    effect.animation = animation;
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectAnimationConfigU32(
                    target,
                    effect_index,
                    config_index,
                    value,
                ),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) && let Some(config) = effect.animation_config.u32(config_index)
                {
                    *config = value;
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectAnimationConfigF32(
                    target,
                    effect_index,
                    config_index,
                    value,
                ),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) && let Some(config) = effect.animation_config.float(config_index)
                {
                    *config = FloatValue::F32(value);
                }
            }
            (
                Some(project),
                UiAction::SetSceneEffectAnimationConfigF32Multiplier(
                    target,
                    effect_index,
                    config_index,
                    value,
                ),
            ) => {
                if let Some(effect) = scene_effect_by_target(
                    project,
                    target,
                    self.selected_scene_instance,
                    effect_index,
                ) && let Some(config) = effect.animation_config.float(config_index)
                {
                    config.set_multiplier(value);
                }
            }
            (Some(project), UiAction::AddSceneEffect(target)) => {
                if let Some(scene_instance) =
                    scene_instance_by_target(project, target, self.selected_scene_instance)
                {
                    scene_instance.scene.add_effect(Default::default());
                }
            }
            (Some(project), UiAction::RemoveSceneEffect(target, effect_index)) => {
                if let Some(scene_instance) =
                    scene_instance_by_target(project, target, self.selected_scene_instance)
                {
                    scene_instance.scene.remove_effect(effect_index);
                }
            }
            (Some(project), UiAction::CloneSceneEffect(target, effect_index)) => {
                if let Some(scene_instance) =
                    scene_instance_by_target(project, target, self.selected_scene_instance)
                    && let Some(effect) = scene_instance.scene.effect(effect_index).cloned()
                {
                    scene_instance.scene.add_effect(effect);
                }
            }
            (None, _) => ignore_without_project(),
            // `apply_action` routes only effect actions here.
            (Some(_), _) => {}
        }
    }
}