1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use crate::quicksilver_compat::graphics::{Background::Col, Color};
use crate::Vector;
use lyon::tessellation::{
    geometry_builder::{Count, GeometryBuilder, GeometryBuilderError, VertexId},
    FillVertex, StrokeVertex, VertexConstructor,
};

use super::{AbstractMesh, AbstractTriangle, AbstractVertex};

/// A way to render complex shapes using the lyon API
///
/// The ShapeRenderer has a color which applies to all incoming shapes.
/// It outputs the shapes to a mutable AbstractMesh reference
pub struct ShapeRenderer<'a> {
    mesh: &'a mut AbstractMesh,
    color: Color,
    dirty: Option<usize>,
}

impl<'a> ShapeRenderer<'a> {
    /// Create a shape renderer with a target mesh and an initial color
    pub fn new(mesh: &'a mut AbstractMesh, color: Color) -> ShapeRenderer<'a> {
        ShapeRenderer {
            mesh,
            color,
            dirty: None,
        }
    }

    /// Get the current color of the incoming shapes
    pub fn color(&self) -> Color {
        self.color
    }

    /// Set the color of the incoming shapes
    pub fn set_color(&mut self, color: Color) {
        self.color = color;
    }
}

impl<'a, Input> GeometryBuilder<Input> for ShapeRenderer<'a>
where
    Color: VertexConstructor<Input, AbstractVertex>,
{
    fn begin_geometry(&mut self) {
        assert!(self.dirty.is_none());
        self.dirty = Some(self.mesh.triangles.len());
    }

    fn end_geometry(&mut self) -> Count {
        let dirty = self
            .dirty
            .expect("begin_geometry must be called before end_geometry");
        self.dirty = None;
        Count {
            vertices: self.mesh.vertices[dirty..].len() as u32,
            indices: self.mesh.triangles[dirty..].len() as u32 * 3,
        }
    }

    fn add_vertex(&mut self, vertex: Input) -> Result<VertexId, GeometryBuilderError> {
        let vertex = self.color.new_vertex(vertex);
        self.mesh.vertices.push(vertex);
        Ok(VertexId(self.mesh.vertices.len() as u32 - 1))
    }

    fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) {
        let triangle = AbstractTriangle::new(0, [a.0, b.0, c.0], Col(Color::WHITE));
        self.mesh.triangles.push(triangle);
    }

    fn abort_geometry(&mut self) {
        let dirty = self
            .dirty
            .expect("begin_geometry must be called before abort_geometry");
        self.dirty = None;
        self.mesh.vertices.truncate(dirty);
        self.mesh.triangles.truncate(dirty);
    }
}

impl VertexConstructor<FillVertex, AbstractVertex> for Color {
    fn new_vertex(&mut self, vertex: FillVertex) -> AbstractVertex {
        let position = Vector::new(vertex.position.x, vertex.position.y);
        AbstractVertex::new(position, None, Col(*self))
    }
}

impl VertexConstructor<StrokeVertex, AbstractVertex> for Color {
    fn new_vertex(&mut self, vertex: StrokeVertex) -> AbstractVertex {
        let position = Vector::new(vertex.position.x, vertex.position.y);
        AbstractVertex::new(position, None, Col(*self))
    }
}