gled 2.28.4

gled is an application for creating animations and effects on artnet or dmx installations
use crate::{
    audio::sound_data::SoundData,
    pipeline::group::Groups,
    storage::{asset::scene::effect::Effect, collections::Collections},
    ui::pills::show_pills,
};
use egui::{
    Button, Color32, CornerRadius, Image, Margin, Rect, Response, Sense, Shape, TextureHandle, Ui,
    Vec2, Widget, load::SizedTexture, pos2,
};
use epaint::RectShape;

pub struct EffectWidget<'a> {
    pub selectable: Option<(&'a mut usize, usize)>,
    pub show_group: bool,
    pub effect: &'a Effect,
    pub svg: Option<TextureHandle>,
    pub groups: Option<&'a Groups>,
    pub groups_show_index: bool,
    /// used for showing the dimmer
    pub beat_progression: Option<f32>,
    pub collections: &'a Collections,
    pub sound_data: &'a SoundData,
}

impl Widget for EffectWidget<'_> {
    fn ui(self, ui: &mut Ui) -> Response {
        let frame = if let Some((selected_effect, index)) = &self.selectable {
            egui::Frame::NONE
                .fill(if *selected_effect == index {
                    Color32::GOLD
                } else {
                    Color32::TRANSPARENT
                })
                .inner_margin(Margin::from(10.0))
                .corner_radius(CornerRadius::from(4.0))
        } else {
            egui::Frame::NONE
                .inner_margin(Margin::from(10.0))
                .corner_radius(CornerRadius::from(4.0))
        };

        let response = frame
            .show(ui, |ui| {
                let mut bg_rect = ui.available_rect_before_wrap() + Margin::same(5);
                ui.painter()
                    .rect_filled(bg_rect, CornerRadius::ZERO, Color32::BLACK);
                if let Some(beat_progression) = self.beat_progression {
                    let dimmer = self.effect.opacity.value(
                        beat_progression,
                        self.collections,
                        self.sound_data,
                    );
                    bg_rect.min.y += (bg_rect.height() * (1.0 - dimmer)).round().max(0.0);
                    ui.painter()
                        .rect_filled(bg_rect, CornerRadius::ZERO, Color32::DARK_GREEN);
                }

                let size = ui.available_size();
                let rect = ui.available_rect_before_wrap();
                ui.allocate_rect(rect, Sense::hover());
                ui.painter().add(Shape::Rect(RectShape::filled(
                    rect,
                    CornerRadius::default(),
                    Color32::BLACK,
                )));

                ui.painter().add(Shape::Rect({
                    let mut shape =
                        RectShape::filled(rect, CornerRadius::default(), Color32::WHITE);
                    if let Some(texture_id) = self.effect.state.texture_id() {
                        shape = shape.with_texture(
                            texture_id,
                            Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)),
                        );
                    }
                    shape
                }));
                if let Some(svg_texture_handle) = self.svg {
                    ui.put(rect, {
                        Image::new(SizedTexture::new(svg_texture_handle.id(), size))
                    });
                }

                if self.show_group {
                    let texts = self
                        .groups
                        .as_ref()
                        .and_then(|groups| groups.get(self.effect.group_index))
                        .map(|group| {
                            vec![(
                                if self.groups_show_index {
                                    format!("{}: {}", self.effect.group_index, group.0)
                                } else {
                                    group.0.clone()
                                },
                                group.color(),
                            )]
                        })
                        .unwrap_or_else(|| {
                            vec![(self.effect.group_index.to_string(), Color32::GOLD)]
                        });
                    show_pills(ui, rect.right_top() + Vec2::new(0.0, 5.0), texts);
                }
            })
            .response;

        if let Some((selected_effect, index)) = self.selectable {
            let res = ui.put(response.rect, Button::new("").fill(Color32::TRANSPARENT));
            if res.clicked() {
                *selected_effect = index;
            }
        }

        response
    }
}