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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//a Imports
use std::cell::{Ref, RefCell};

use crate::BufferAccessor;
use crate::{Renderable, VertexAttr};

//a Vertices
//tp Vertices
/// A set of vertices using one or more [crate::BufferData] through [BufferAccessor]s.
///
/// A number of [Vertices] is used by an `Object`, its components and their meshes; one is used for each primitive within a mesh for its elements.
/// The actual elements will be sets of triangles (as stripes or
/// whatever) which use these vertices.
///
/// A [Vertices] object includes a lot of options for vertices, and
/// different renderers (or different render stages) may require
/// different subsets of these indices. As such, in OpenGL for
/// example, a [Vertices] object may end up with more than one
/// `VAO`. This data is part of the [VerticesClient] struct
/// associated with the [Vertices]
///
/// When it comes to creating an instance of a mesh, that instance
/// will have specific transformations and materials for each of its
/// primitives; rendering the instance with a shader will require
/// enabling the [Vertices] client for that shader, setting
/// appropriate render options (uniforms in OpenGL)
#[derive(Debug)]
pub struct Vertices<'vertices, R: Renderable + ?Sized> {
    indices: &'vertices BufferAccessor<'vertices, R>,
    position: &'vertices BufferAccessor<'vertices, R>,
    rc_client: RefCell<R::Vertices>,
    attrs: Vec<(VertexAttr, &'vertices BufferAccessor<'vertices, R>)>,
}

//ip Display for Vertices
impl<'vertices, R: Renderable> std::fmt::Display for Vertices<'vertices, R>
where
    R: Renderable,
{
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        writeln!(fmt, "Vertices:")?;
        writeln!(fmt, "  indices: {:?}", self.indices)?;
        writeln!(fmt, "  position: {:?}", self.position)?;
        for (n, a) in &self.attrs {
            writeln!(fmt, "  {n:?}: {a:?}")?;
        }
        Ok(())
    }
}

///ip Vertices
impl<'vertices, R: Renderable> Vertices<'vertices, R> {
    //fp new
    /// Create a new [Vertices] object with no additional attributes
    pub fn new(
        indices: &'vertices BufferAccessor<'vertices, R>,
        position: &'vertices BufferAccessor<'vertices, R>,
    ) -> Self {
        let attrs = Vec::new();
        let rc_client = RefCell::new(R::Vertices::default());
        Self {
            indices,
            position,
            rc_client,
            attrs,
        }
    }

    //mp add_attr
    /// Add a [BufferAccessor] for a particular [VertexAttr]
    ///
    /// On creation the [Vertices] will have views for indices and
    /// positions; this provides a means to add views for things such
    /// as normal, tex coords, etc
    pub fn add_attr(
        &mut self,
        attr: VertexAttr,
        accessor: &'vertices BufferAccessor<'vertices, R>,
    ) {
        self.attrs.push((attr, accessor));
    }

    //mp borrow_indices
    /// Borrow the indices [BufferAccessor]
    pub fn borrow_indices<'a>(&'a self) -> &'a BufferAccessor<'vertices, R> {
        self.indices
    }

    //mp borrow_position
    /// Borrow the position [BufferAccessor]
    pub fn borrow_position<'a>(&'a self) -> &'a BufferAccessor<'vertices, R> {
        self.position
    }

    //mp borrow_attr
    /// Borrow an attribute [BufferAccessor] if the [Vertices] has one
    pub fn borrow_attr<'a>(&'a self, attr: VertexAttr) -> Option<&'a BufferAccessor<'vertices, R>> {
        for i in 0..self.attrs.len() {
            if self.attrs[i].0 == attr {
                return Some(self.attrs[i].1);
            }
        }
        None
    }

    //mp iter_attrs
    /// Iterate through attributes
    pub fn iter_attrs(&self) -> std::slice::Iter<(VertexAttr, &BufferAccessor<'vertices, R>)> {
        self.attrs.iter()
    }

    //mp create_client
    /// Create the render buffer required by the BufferAccessor
    pub fn create_client(&self, renderer: &mut R) {
        self.indices.create_client(VertexAttr::Indices, renderer);
        self.position.create_client(VertexAttr::Position, renderer);
        for (attr, view) in self.iter_attrs() {
            view.create_client(*attr, renderer);
        }
        *(self.rc_client.borrow_mut()) = renderer.create_vertices_client(self);
    }

    //ap borrow_client
    /// Borrow the client
    pub fn borrow_client(&self) -> Ref<R::Vertices> {
        self.rc_client.borrow()
    }

    //zz All done
}