#[cfg(feature = "runtime")]
mod tessellate;
#[cfg(feature = "runtime")]
pub mod runtime;
use egui::{epaint::Vertex, Color32, Mesh, Painter, Pos2, Rect, Response, Sense, Ui, Vec2};
#[derive(Debug, Clone)]
pub struct IconData {
pub name: &'static str,
pub vertices: &'static [(f32, f32)],
pub indices: &'static [u32],
pub viewbox_width: f32,
pub viewbox_height: f32,
}
#[derive(Debug, Clone)]
pub struct OwnedIconData {
pub name: String,
pub vertices: Vec<(f32, f32)>,
pub indices: Vec<u32>,
pub viewbox_width: f32,
pub viewbox_height: f32,
}
pub fn render_icon_data(
painter: &Painter,
rect: Rect,
vertices: &[(f32, f32)],
indices: &[u32],
viewbox_width: f32,
viewbox_height: f32,
color: Color32,
) {
let scale_x = rect.width() / viewbox_width;
let scale_y = rect.height() / viewbox_height;
let scale = scale_x.min(scale_y);
let offset_x = rect.left() + viewbox_width.mul_add(-scale, rect.width()) / 2.0;
let offset_y = rect.top() + viewbox_height.mul_add(-scale, rect.height()) / 2.0;
let mut mesh = Mesh::default();
for &(x, y) in vertices {
let pos = Pos2::new(offset_x + x * scale, offset_y + y * scale);
mesh.vertices.push(Vertex {
pos,
uv: Pos2::ZERO,
color,
});
}
mesh.indices.extend_from_slice(indices);
painter.add(mesh);
}
pub fn render_icon(painter: &Painter, rect: Rect, icon_data: &IconData, color: Color32) {
render_icon_data(
painter,
rect,
icon_data.vertices,
icon_data.indices,
icon_data.viewbox_width,
icon_data.viewbox_height,
color,
);
}
impl OwnedIconData {
pub fn render(&self, painter: &Painter, rect: Rect, color: Color32) {
render_icon_data(
painter,
rect,
&self.vertices,
&self.indices,
self.viewbox_width,
self.viewbox_height,
color,
);
}
}
pub struct Icon<'a> {
vertices: &'a [(f32, f32)],
indices: &'a [u32],
viewbox_width: f32,
viewbox_height: f32,
size: f32,
color: Color32,
}
impl<'a> Icon<'a> {
#[must_use]
pub const fn new(icon_data: &'a IconData) -> Self {
Self {
vertices: icon_data.vertices,
indices: icon_data.indices,
viewbox_width: icon_data.viewbox_width,
viewbox_height: icon_data.viewbox_height,
size: 24.0,
color: Color32::WHITE,
}
}
#[must_use]
pub fn from_owned(data: &'a OwnedIconData) -> Self {
Self {
vertices: &data.vertices,
indices: &data.indices,
viewbox_width: data.viewbox_width,
viewbox_height: data.viewbox_height,
size: 24.0,
color: Color32::WHITE,
}
}
#[must_use]
pub const fn size(mut self, size: f32) -> Self {
self.size = size;
self
}
#[must_use]
pub const fn color(mut self, color: Color32) -> Self {
self.color = color;
self
}
pub fn show(self, ui: &mut Ui) -> Response {
let (rect, response) = ui.allocate_exact_size(Vec2::splat(self.size), Sense::click());
if ui.is_rect_visible(rect) {
if self.vertices.is_empty() {
ui.painter().rect_filled(rect, 2.0, Color32::from_gray(100));
} else {
render_icon_data(
ui.painter(),
rect,
self.vertices,
self.indices,
self.viewbox_width,
self.viewbox_height,
self.color,
);
}
}
response
}
}