use std::marker::PhantomData;
use crate::{render::resource::TrackedRenderPass, tcs::world::World};
pub trait Draw<P: PhaseItem>: 'static {
fn draw<'w>(&self, pass: &mut TrackedRenderPass<'w>, wold: &'w World, item: &P);
}
pub trait PhaseItem {
type SortKey: Ord;
fn sort_key(&self) -> Self::SortKey;
fn draw_function(&self) -> &dyn Draw<Self>;
}
pub trait RenderCommand<P: PhaseItem> {
fn render<'w>(
world: &'w World,
item: &P,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult;
}
pub enum RenderCommandResult {
Success,
Failure,
}
macro_rules! render_command_tuple_impl {
($($name: ident),*) => {
impl<P: PhaseItem, $($name: RenderCommand<P>),*> RenderCommand<P> for ($($name,)*) {
#[allow(non_snake_case)]
fn render<'w>(
world: &'w World,
item: &P,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult{
$(if let RenderCommandResult::Failure = $name::render(world, item, pass) {
return RenderCommandResult::Failure;
})*
RenderCommandResult::Success
}
}
};
}
render_command_tuple_impl!(C0);
render_command_tuple_impl!(C0, C1);
render_command_tuple_impl!(C0, C1, C2);
render_command_tuple_impl!(C0, C1, C2, C3);
render_command_tuple_impl!(C0, C1, C2, C3, C4);
pub struct DrawState<C, P> {
phantom_p: PhantomData<P>,
phantom_c: PhantomData<C>,
}
impl<C, P> DrawState<C, P> {
pub(crate) fn new() -> Self {
DrawState {
phantom_p: Default::default(),
phantom_c: Default::default(),
}
}
}
impl<P: 'static, C: 'static> Draw<P> for DrawState<P, C>
where
P: PhaseItem,
C: RenderCommand<P>,
{
fn draw<'w>(&self, pass: &mut TrackedRenderPass<'w>, world: &'w World, item: &P) {
C::render(world, item, pass);
}
}