1use alloc::vec::Vec;
4use core::borrow::Borrow;
5
6use crate::geom::{mesh, Mesh, Tri};
7use crate::math::{mat::Mat4x4, vary::Vary};
8
9use super::{ctx::Context, target::Target, NdcToScreen, Shader};
10
11#[derive(Clone, Debug, Default)]
30pub struct Batch<Vtx, Uni, Shd, Tgt, Ctx> {
31 faces: Vec<Tri<usize>>,
32 verts: Vec<Vtx>,
33 uniform: Uni,
34 shader: Shd,
35 viewport: Mat4x4<NdcToScreen>,
36 target: Tgt,
37 ctx: Ctx,
38}
39
40macro_rules! update {
41 ($($upd:ident)+ ; $self:ident $($rest:ident)+) => {{
42 let Self { $($upd: _, )+ $($rest, )+ } = $self;
43 Batch { $($upd, )+ $($rest, )+ }
44 }};
45}
46
47impl Batch<(), (), (), (), Context> {
48 pub fn new() -> Self {
49 Self::default()
50 }
51}
52
53impl<Vtx, Uni, Shd, Tgt, Ctx> Batch<Vtx, Uni, Shd, Tgt, Ctx> {
54 pub fn faces(self, faces: impl AsRef<[Tri<usize>]>) -> Self {
58 Self {
59 faces: faces.as_ref().to_vec(),
60 ..self
61 }
62 }
63
64 pub fn vertices<V: Clone>(
69 self,
70 verts: impl AsRef<[V]>,
71 ) -> Batch<V, Uni, Shd, Tgt, Ctx> {
72 let verts = verts.as_ref().to_vec();
73 update!(verts; self faces uniform shader viewport target ctx)
74 }
75
76 pub fn mesh<A: Clone>(
78 self,
79 mesh: &Mesh<A>,
80 ) -> Batch<mesh::Vertex<A>, Uni, Shd, Tgt, Ctx> {
81 let faces = mesh.faces.clone();
82 let verts = mesh.verts.clone();
83 update!(verts faces; self uniform shader viewport target ctx)
84 }
85
86 pub fn uniform<U: Copy>(self, uniform: U) -> Batch<Vtx, U, Shd, Tgt, Ctx> {
88 update!(uniform; self verts faces shader viewport target ctx)
89 }
90
91 pub fn shader<V: Vary, S: Shader<Vtx, V, Uni>>(
93 self,
94 shader: S,
95 ) -> Batch<Vtx, Uni, S, Tgt, Ctx> {
96 update!(shader; self verts faces uniform viewport target ctx)
97 }
98
99 pub fn viewport(self, viewport: Mat4x4<NdcToScreen>) -> Self {
101 update!(viewport; self verts faces uniform shader target ctx)
102 }
103
104 pub fn target<T>(self, target: T) -> Batch<Vtx, Uni, Shd, T, Ctx> {
106 update!(target; self verts faces uniform shader viewport ctx)
107 }
108
109 pub fn context(self, ctx: &Context) -> Batch<Vtx, Uni, Shd, Tgt, &Context> {
111 update!(ctx; self verts faces uniform shader viewport target)
112 }
113}
114
115impl<Vtx: Clone, Uni: Copy, Shd, Tgt: Target, Ctx>
116 Batch<Vtx, Uni, Shd, &mut Tgt, Ctx>
117where
118 Ctx: Borrow<Context>,
119{
120 pub fn render<V: Vary>(&mut self)
122 where
123 Shd: Shader<Vtx, V, Uni>,
124 {
125 #[rustfmt::skip]
126 let Self {
127 faces, verts, shader, uniform, viewport, target, ctx,
128 } = self;
129 super::render(
130 faces,
131 verts,
132 shader,
133 *uniform,
134 *viewport,
135 *target,
136 (*ctx).borrow(),
137 );
138 }
139}