use gled_protocol::assets::KnownAsset;
use std::sync::Arc;
use egui::{
Color32, Mesh, Rect, Shape, Vec2,
epaint::{Vertex, WHITE_UV},
};
use crate::ui::{color::ToColor32, curve_editor::CurveEditor, pills::show_pills};
use gled_model::asset::{
animation::Animation, curve::Curve, midi_controller::MidiController,
output_device::OutputDevice, palette::Palette, project::Project, scene::Scene,
};
pub(crate) trait AssetUi: KnownAsset {
fn show(&self, ui: &mut egui::Ui, rect: Rect) {
let _ = (ui, rect);
}
}
impl AssetUi for Animation {}
impl AssetUi for MidiController {}
impl AssetUi for OutputDevice {}
impl AssetUi for Project {}
impl AssetUi for Curve {
fn show(&self, ui: &mut egui::Ui, rect: Rect) {
let mut min = rect.min;
min.x = rect.max.x - 64.0;
let rect = Rect::from_min_max(min, rect.max);
let mut curve = self.clone();
curve.draw_curve(ui, false, None, rect);
}
}
impl AssetUi for Palette {
fn show(&self, ui: &mut egui::Ui, rect: Rect) {
let mesh = {
const COLOR_GRADIENT_RATIO: f32 = 0.35;
const GAP: f32 = 2.0;
const BORDER: f32 = 1.0;
const HEIGHT: f32 = 18.0;
let available_width = rect.width() - GAP - 4.0 * BORDER;
let color_width = available_width * COLOR_GRADIENT_RATIO;
let gradient_with: f32 = available_width - color_width;
let width_per_gradient_color = gradient_with / 16.0;
let start_pos = rect.right_center();
let mut mesh = Mesh::default();
mesh.add_colored_rect(
Rect::from_min_max(
start_pos
- Vec2::new(
BORDER + color_width + BORDER + GAP + BORDER + gradient_with + BORDER,
HEIGHT / 2.0,
),
start_pos - Vec2::new(GAP + BORDER + gradient_with + BORDER, -HEIGHT / 2.0),
),
Color32::BLACK,
);
let index = mesh.vertices.len() as u32;
mesh.add_triangle(index, index + 1, index + 2);
mesh.add_triangle(index + 3, index + 4, index + 5);
let primary_color = self.primary.color32();
mesh.vertices.push(Vertex {
pos: start_pos
- Vec2::new(
color_width + BORDER + GAP + BORDER + gradient_with + BORDER,
HEIGHT / 2.0 - BORDER,
),
uv: WHITE_UV,
color: primary_color,
});
mesh.vertices.push(Vertex {
pos: start_pos
- Vec2::new(
BORDER + GAP + BORDER + gradient_with + BORDER,
HEIGHT / 2.0 - BORDER,
),
uv: WHITE_UV,
color: primary_color,
});
mesh.vertices.push(Vertex {
pos: start_pos
- Vec2::new(
color_width + BORDER + GAP + BORDER + gradient_with + BORDER,
-HEIGHT / 2.0 + BORDER,
),
uv: WHITE_UV,
color: primary_color,
});
let secondary_color = self.secondary.color32();
mesh.vertices.push(Vertex {
pos: start_pos
- Vec2::new(
BORDER + GAP + BORDER + gradient_with + BORDER,
HEIGHT / 2.0 - BORDER,
),
uv: WHITE_UV,
color: secondary_color,
});
mesh.vertices.push(Vertex {
pos: start_pos
- Vec2::new(
color_width + BORDER + GAP + BORDER + gradient_with + BORDER,
-HEIGHT / 2.0 + BORDER,
),
uv: WHITE_UV,
color: secondary_color,
});
mesh.vertices.push(Vertex {
pos: start_pos
- Vec2::new(
BORDER + GAP + BORDER + gradient_with + BORDER,
-HEIGHT / 2.0 + BORDER,
),
uv: WHITE_UV,
color: secondary_color,
});
mesh.add_colored_rect(
Rect::from_min_max(
start_pos - Vec2::new(BORDER + gradient_with + BORDER, HEIGHT / 2.0),
start_pos - Vec2::new(BORDER, -HEIGHT / 2.0),
),
Color32::BLACK,
);
for (i, color) in self.gradient.into_iter().rev().enumerate() {
mesh.add_colored_rect(
Rect::from_min_max(
start_pos
- Vec2::new(
width_per_gradient_color * (i + 1) as f32 + BORDER,
HEIGHT / 2.0 - BORDER,
),
start_pos
- Vec2::new(
width_per_gradient_color * i as f32 + BORDER,
-HEIGHT / 2.0 + BORDER,
),
),
color.color32(),
);
}
mesh
};
ui.painter().add(Shape::Mesh(Arc::new(mesh)));
}
}
impl AssetUi for Scene {
fn show(&self, ui: &mut egui::Ui, rect: egui::Rect) {
show_pills(
ui,
rect.right_top() + Vec2::new(0.0, 1.0),
self.group_indices()
.into_iter()
.map(|index| (index.to_string(), Color32::GOLD))
.collect(),
);
}
}