use bevy::prelude::*;
use lyon::tessellation::{FillVertex, GeometryBuilderError, StrokeVertex, VertexId};
use lyon::tessellation::geometry_builder::{
FillGeometryBuilder, GeometryBuilder, StrokeGeometryBuilder,
};
use crate::draw::mesh::MeshExt;
pub struct MeshBuilder<'a, A> {
mesh: &'a mut Mesh,
begin_vertex_count: u32,
begin_index_count: u32,
transform: Mat4,
attributes: A,
}
pub struct SingleColor(Color);
pub struct Vertex;
impl<'a, A> MeshBuilder<'a, A> {
fn new(mesh: &'a mut Mesh, transform: Mat4, attributes: A) -> Self {
MeshBuilder {
mesh,
begin_vertex_count: 0,
begin_index_count: 0,
transform,
attributes,
}
}
}
impl<'a> MeshBuilder<'a, SingleColor> {
pub fn single_color(mesh: &'a mut Mesh, transform: Mat4, color: Color) -> Self {
Self::new(mesh, transform, SingleColor(color))
}
}
impl<'a> MeshBuilder<'a, Vertex> {
pub fn vertex_per_point(mesh: &'a mut Mesh, transform: Mat4) -> Self {
Self::new(mesh, transform, Vertex)
}
}
impl<'a, A> GeometryBuilder for MeshBuilder<'a, A> {
fn begin_geometry(&mut self) {
self.begin_vertex_count = self.mesh.count_vertices() as u32;
self.begin_index_count = self.mesh.count_indices() as u32;
}
fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) {
self.mesh.push_index(c.to_usize() as u32);
self.mesh.push_index(b.to_usize() as u32);
self.mesh.push_index(a.to_usize() as u32);
}
fn abort_geometry(&mut self) {
unimplemented!();
}
}
impl<'a> FillGeometryBuilder for MeshBuilder<'a, SingleColor> {
fn add_fill_vertex(
&mut self,
mut vertex: FillVertex,
) -> Result<VertexId, GeometryBuilderError> {
let id = VertexId::from_usize(self.mesh.count_vertices());
let position = vertex.position();
let p = Vec2::new(position.x, position.y).extend(0.0);
let point = self.transform.transform_point3(p);
let SingleColor(color) = self.attributes;
let attr = vertex.interpolated_attributes();
let tex_coords = if attr.is_empty() {
[0.0, 0.0]
} else {
[attr[0], attr[1]]
};
self.mesh.points_mut().push(point.to_array());
self.mesh
.colors_mut()
.push(color.to_linear().to_f32_array());
self.mesh.tex_coords_mut().push(tex_coords);
self.mesh.normals_mut().push([0.0, 0.0, 1.0]);
Ok(id)
}
}
impl<'a> StrokeGeometryBuilder for MeshBuilder<'a, SingleColor> {
fn add_stroke_vertex(
&mut self,
mut vertex: StrokeVertex,
) -> Result<VertexId, GeometryBuilderError> {
let id = VertexId::from_usize(self.mesh.count_vertices());
let position = vertex.position();
let p = Vec2::new(position.x, position.y).extend(0.0);
let point = self.transform.transform_point3(p);
let SingleColor(color) = self.attributes;
let attr = vertex.interpolated_attributes();
let tex_coords = if attr.is_empty() {
[0.0, 0.0]
} else {
[attr[0], attr[1]]
};
self.mesh.points_mut().push(point.to_array());
self.mesh
.colors_mut()
.push(color.to_linear().to_f32_array());
self.mesh.tex_coords_mut().push(tex_coords);
self.mesh.normals_mut().push([0.0, 0.0, 1.0]);
Ok(id)
}
}
impl<'a> FillGeometryBuilder for MeshBuilder<'a, Vertex> {
fn add_fill_vertex(
&mut self,
mut vertex: FillVertex,
) -> Result<VertexId, GeometryBuilderError> {
let id = VertexId::from_usize(self.mesh.count_vertices());
let position = vertex.position();
let p = Vec2::new(position.x, position.y).extend(0.0);
let point = self.transform.transform_point3(p);
let attr = vertex.interpolated_attributes();
let color = Vec4::new(attr[0], attr[1], attr[2], attr[3]);
let tex_coords = Vec2::new(attr[4], attr[5]);
self.mesh.points_mut().push(point.to_array());
self.mesh.colors_mut().push(color.to_array());
self.mesh.tex_coords_mut().push(tex_coords.to_array());
self.mesh.normals_mut().push([0.0, 0.0, 1.0]);
Ok(id)
}
}
impl<'a> StrokeGeometryBuilder for MeshBuilder<'a, Vertex> {
fn add_stroke_vertex(
&mut self,
mut vertex: StrokeVertex,
) -> Result<VertexId, GeometryBuilderError> {
let id = VertexId::from_usize(self.mesh.count_vertices());
let position = vertex.position();
let p = Vec2::new(position.x, position.y).extend(0.0);
let point = self.transform.transform_point3(p);
let attr = vertex.interpolated_attributes();
let color = Vec4::new(attr[0], attr[1], attr[2], attr[3]);
let tex_coords = Vec2::new(attr[4], attr[5]);
self.mesh.points_mut().push(point.to_array());
self.mesh.colors_mut().push(color.to_array());
self.mesh.tex_coords_mut().push(tex_coords.to_array());
self.mesh.normals_mut().push([0.0, 0.0, 1.0]);
Ok(id)
}
}