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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
mod shapes;
mod transform;

pub use shapes::*;
pub use transform::*;

use super::{
    BoxedGeometry, Color, Command, Draw, DrawList, DrawState, Geometry, GeometryVariants,
    LineState, LineVertex, Projection, TextureCache,
};
use solstice::texture::Texture;

#[derive(Debug, PartialEq, Copy, Clone, solstice::vertex::Vertex)]
#[repr(C)]
pub struct Vertex3D {
    pub position: [f32; 3],
    pub uv: [f32; 2],
    pub color: [f32; 4],
    pub normal: [f32; 3],
}

impl<'a, V, I, G> BoxedGeometry<'a, Vertex3D, u32> for G
where
    V: Iterator<Item = Vertex3D> + 'a,
    I: Iterator<Item = u32> + 'a,
    G: Geometry<Vertex3D, Vertices = V, Indices = I> + dyn_clone::DynClone + std::fmt::Debug,
{
    fn vertices(&self) -> std::boxed::Box<dyn Iterator<Item = Vertex3D> + 'a> {
        std::boxed::Box::new(Geometry::vertices(self))
    }

    fn indices(&self) -> std::boxed::Box<dyn Iterator<Item = u32> + 'a> {
        std::boxed::Box::new(Geometry::indices(self))
    }
}
dyn_clone::clone_trait_object!(BoxedGeometry<'_, Vertex3D, u32>);

impl<G> Draw<Vertex3D, G> for DrawList<'_>
where
    G: Geometry<Vertex3D> + Clone + 'static,
{
    fn draw(&mut self, geometry: G) {
        self.draw_with_color_and_transform(geometry, self.color, self.transform)
    }

    fn draw_with_transform<TX: Into<Transform3D>>(&mut self, geometry: G, transform: TX) {
        self.draw_with_color_and_transform(geometry, self.color, transform)
    }

    fn draw_with_color<C: Into<Color>>(&mut self, geometry: G, color: C) {
        self.draw_with_color_and_transform(geometry, color, self.transform)
    }

    fn draw_with_color_and_transform<C: Into<Color>, TX: Into<Transform3D>>(
        &mut self,
        geometry: G,
        color: C,
        transform: TX,
    ) {
        self.commands.push(Command::Draw(DrawState {
            data: GeometryVariants::D3(std::boxed::Box::new(geometry)),
            transform: transform.into(),
            camera: self.camera,
            projection_mode: self
                .projection_mode
                .unwrap_or(Projection::Perspective(None)),
            color: color.into(),
            texture: None,
            target: self.target.clone(),
            shader: self.shader.clone(),
        }))
    }

    fn stroke(&mut self, geometry: G) {
        self.stroke_with_color_and_transform(geometry, self.color, self.transform)
    }

    fn stroke_with_transform<TX: Into<Transform3D>>(&mut self, geometry: G, transform: TX) {
        self.stroke_with_color_and_transform(geometry, self.color, transform)
    }

    fn stroke_with_color<C: Into<Color>>(&mut self, geometry: G, color: C) {
        self.stroke_with_color_and_transform(geometry, color, self.transform)
    }

    fn stroke_with_color_and_transform<C: Into<Color>, TX: Into<Transform3D>>(
        &mut self,
        geometry: G,
        color: C,
        transform: TX,
    ) {
        self.commands.push(Command::Line(DrawState {
            data: LineState {
                geometry: std::boxed::Box::new(
                    geometry
                        .vertices()
                        .map(|v: Vertex3D| LineVertex {
                            position: v.position,
                            width: 5.0,
                            color: [1., 1., 1., 1.],
                        })
                        .collect::<Vec<_>>()
                        .into_iter(),
                ),
                is_loop: true,
                depth_buffer: false,
            },
            transform: transform.into(),
            camera: self.camera,
            projection_mode: self
                .projection_mode
                .unwrap_or(Projection::Perspective(None)),
            color: color.into(),
            texture: None,
            target: self.target.clone(),
            shader: self.shader.clone(),
        }))
    }

    fn image<T: Texture>(&mut self, geometry: G, texture: T) {
        self.image_with_color_and_transform(geometry, texture, self.color, self.transform)
    }

    fn image_with_color<T, C>(&mut self, geometry: G, texture: T, color: C)
    where
        T: Texture,
        C: Into<Color>,
    {
        self.image_with_color_and_transform(geometry, texture, color, self.transform)
    }

    fn image_with_transform<T, TX>(&mut self, geometry: G, texture: T, transform: TX)
    where
        T: Texture,
        TX: Into<Transform3D>,
    {
        self.image_with_color_and_transform(geometry, texture, self.color, transform)
    }

    fn image_with_color_and_transform<T, C, TX>(
        &mut self,
        geometry: G,
        texture: T,
        color: C,
        transform: TX,
    ) where
        T: Texture,
        C: Into<Color>,
        TX: Into<Transform3D>,
    {
        self.commands.push(Command::Draw(DrawState {
            data: GeometryVariants::D3(std::boxed::Box::new(geometry)),
            transform: transform.into(),
            camera: self.camera,
            projection_mode: self
                .projection_mode
                .unwrap_or(Projection::Perspective(None)),
            color: color.into(),
            texture: Some(TextureCache {
                ty: texture.get_texture_type(),
                key: texture.get_texture_key(),
                info: texture.get_texture_info(),
            }),
            target: self.target.clone(),
            shader: self.shader.clone(),
        }))
    }
}