use alloc::vec::Vec;
use core::borrow::Borrow;
use crate::{
geom::{Mesh, Tri, Vertex3},
math::{Lerp, mat::Mat4x4, vary::Vary},
};
use super::{Context, NdcToScreen, Shader, Target};
#[derive(Clone, Debug, Default)]
pub struct Batch<Vtx, Uni, Shd, Tgt, Ctx> {
faces: Vec<Tri<usize>>,
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<Vtx, Uni, Shd, Tgt, Ctx> Batch<Vtx, Uni, Shd, Tgt, Ctx> {
pub fn faces(self, faces: impl AsRef<[Tri<usize>]>) -> Self {
Self {
faces: faces.as_ref().to_vec(),
..self
}
}
pub fn vertices<V: Clone>(
self,
verts: impl AsRef<[V]>,
) -> Batch<V, Uni, Shd, Tgt, Ctx> {
let verts = verts.as_ref().to_vec();
update!(verts; self faces uniform shader viewport target ctx)
}
pub fn mesh<A: Clone>(
self,
mesh: &Mesh<A>,
) -> Batch<Vertex3<A>, Uni, Shd, Tgt, Ctx> {
let faces = mesh.faces.clone();
let verts = mesh.verts.clone();
update!(verts faces; self uniform shader viewport target ctx)
}
pub fn uniform<U: Copy>(self, uniform: U) -> Batch<Vtx, U, Shd, Tgt, Ctx> {
update!(uniform; self verts faces shader viewport target ctx)
}
pub fn shader<V: Vary, S: Shader<Vtx, V, Uni>>(
self,
shader: S,
) -> Batch<Vtx, Uni, S, Tgt, Ctx> {
update!(shader; self verts faces uniform viewport target ctx)
}
pub fn viewport(self, viewport: Mat4x4<NdcToScreen>) -> Self {
update!(viewport; self verts faces uniform shader target ctx)
}
pub fn target<T>(self, target: T) -> Batch<Vtx, Uni, Shd, T, Ctx> {
update!(target; self verts faces uniform shader viewport ctx)
}
pub fn context(self, ctx: &Context) -> Batch<Vtx, Uni, Shd, Tgt, &Context> {
update!(ctx; self verts faces uniform shader viewport target)
}
}
impl<Vtx: Clone, Uni: Copy, Shd, Tgt: Target, Ctx>
Batch<Vtx, Uni, Shd, &mut Tgt, Ctx>
where
Ctx: Borrow<Context>,
{
#[rustfmt::skip]
pub fn render<V: Lerp + Vary>(&mut self)
where
Shd: Shader<Vtx, V, Uni>,
{
let Self {
faces, verts, shader, uniform, viewport, target, ctx,
} = self;
super::render(
faces, verts, shader, *uniform, *viewport, *target,
(*ctx).borrow(),
);
}
}