use alloc::vec::Vec;
use core::borrow::Borrow;
use crate::{
geom::{Mesh, Tri, Vertex3},
math::{Mat4x4, Vary},
};
use super::{Clip, Context, NdcToScreen, Render, Shader, Target};
#[derive(Clone, Debug, Default)]
pub struct Batch<Prim, Vtx, Uni, Shd, Tgt, Ctx> {
prims: Vec<Prim>,
verts: Vec<Vtx>,
uniform: Uni,
shader: Shd,
viewport: Mat4x4<NdcToScreen>,
target: Tgt,
ctx: Ctx,
}
macro_rules! update {
($($upd:ident)+ ; $self:ident $($rest:ident)+) => {{
let Self { $($upd: _, )+ $($rest, )+ } = $self;
Batch { $($upd, )+ $($rest, )+ }
}};
}
impl Batch<(), (), (), (), (), Context> {
pub fn new() -> Self {
Self::default()
}
}
impl<Prim, Vtx, Uni, Shd, Tgt, Ctx> Batch<Prim, Vtx, Uni, Shd, Tgt, Ctx> {
pub fn primitives<P: Clone>(
self,
prims: impl AsRef<[P]>,
) -> Batch<P, Vtx, Uni, Shd, Tgt, Ctx> {
let prims = prims.as_ref().to_vec();
update!(prims; self verts uniform shader viewport target ctx)
}
pub fn vertices<V: Clone>(
self,
verts: impl AsRef<[V]>,
) -> Batch<Prim, V, Uni, Shd, Tgt, Ctx> {
let verts = verts.as_ref().to_vec();
update!(verts; self prims uniform shader viewport target ctx)
}
pub fn mesh<A: Clone>(
self,
mesh: &Mesh<A>,
) -> Batch<Tri<usize>, Vertex3<A>, Uni, Shd, Tgt, Ctx> {
let prims = mesh.faces.clone();
let verts = mesh.verts.clone();
update!(verts prims; self uniform shader viewport target ctx)
}
pub fn uniform<U: Copy>(
self,
uniform: U,
) -> Batch<Prim, Vtx, U, Shd, Tgt, Ctx> {
update!(uniform; self verts prims shader viewport target ctx)
}
pub fn shader<V: Vary, U, S: Shader<Vtx, V, U>>(
self,
shader: S,
) -> Batch<Prim, Vtx, Uni, S, Tgt, Ctx> {
update!(shader; self verts prims uniform viewport target ctx)
}
pub fn viewport(self, viewport: Mat4x4<NdcToScreen>) -> Self {
update!(viewport; self verts prims uniform shader target ctx)
}
pub fn target<T>(self, target: T) -> Batch<Prim, Vtx, Uni, Shd, T, Ctx> {
update!(target; self verts prims uniform shader viewport ctx)
}
pub fn context(
self,
ctx: &Context,
) -> Batch<Prim, Vtx, Uni, Shd, Tgt, &Context> {
update!(ctx; self verts prims uniform shader viewport target)
}
}
impl<Prim, Vtx, Uni, Shd, Tgt, Ctx> Batch<Prim, Vtx, Uni, Shd, &mut Tgt, Ctx> {
#[rustfmt::skip]
pub fn render<Var>(&mut self)
where
Var: Vary,
Prim: Render<Var> + Clone,
Vtx: Clone,
Uni: Copy,
[<Prim>::Clip]: Clip<Item= Prim::Clip>,
Shd: Shader<Vtx, Var, Uni>,
Tgt: Target,
Ctx: Borrow<Context>
{
let Self {
prims, verts, shader, uniform, viewport, target, ctx,
} = self;
super::render(
prims, verts, shader, *uniform, *viewport, *target,
(*ctx).borrow(),
);
}
}