use super::super::PMesh;
use super::PBuilder;
use crate::IndexType;
use lyon::math::Point;
use lyon::tessellation::geometry_builder::{MaxIndex, Positions};
pub use lyon::tessellation::StrokeBuilder;
use lyon::tessellation::{
BuffersBuilder, StrokeOptions, StrokeTessellator, VertexBuffers, VertexId,
};
use std::ops::Add;
pub struct PStroke<T>
where
T: Add + IndexType + From<VertexId> + MaxIndex,
{
tessellator: StrokeTessellator,
options: StrokeOptions,
geometry: VertexBuffers<Point, T>,
}
impl<T> PStroke<T>
where
T: Add + IndexType + From<VertexId> + MaxIndex,
{
pub fn new(width: f32, tol: f32) -> Self {
let geometry: VertexBuffers<Point, T> = VertexBuffers::new();
let tessellator = StrokeTessellator::new();
let options = StrokeOptions::tolerance(tol).with_line_width(width);
PStroke {
tessellator,
options,
geometry,
}
}
pub fn draw<F>(&mut self, draw_commands: F) -> &mut Self
where
F: FnOnce(&mut PBuilder<StrokeBuilder>),
{
let geometry_builder = &mut BuffersBuilder::new(&mut self.geometry, Positions);
let builder = self.tessellator.builder(&self.options, geometry_builder);
let mut my_builder = PBuilder::new(builder);
draw_commands(&mut my_builder);
my_builder.build().unwrap();
self
}
pub fn build(self) -> PMesh<T> {
PMesh::import_geometry(&self.geometry, false)
}
}
impl<T> PMesh<T>
where
T: Add + IndexType + From<VertexId> + MaxIndex,
{
pub fn stroke<F>(&mut self, width: f32, tol: f32, draw_commands: F) -> &mut PMesh<T>
where
F: FnOnce(&mut PBuilder<StrokeBuilder>),
{
let mut tessellator = PStroke::<T>::new(width, tol);
tessellator.draw(draw_commands);
self.extend(&tessellator.build());
self
}
}