use crate::render::render_engine::RenderEngine;
pub trait EngineComponent<T> {
fn create(engine: &mut RenderEngine) -> Self;
fn start(&mut self, other: T);
fn update(&mut self, other: T);
fn render<'rpass>(&'rpass mut self, render_engine: &'rpass RenderEngine, pass: &mut wgpu::RenderPass<'rpass>);
fn exit(&mut self, other: T);
}
#[macro_export]
macro_rules! create_app {
{
CLEAR_COLOR = $color:expr,
APP {$(
$component:ident: $type:ty[$($param:ident),*]
),*},
PASSES {$(
$pass_idx:literal: {
PARTS: [$(
{
PIPELINE: $pipeline:expr,
PREPARE: [$($prepare:ident),*],
RENDER: $to_render:ident,
}
),*],
DEPTH: $depth:literal
}
),*}
} => {
use forte_engine::{EngineApp, start_render, end_render, pass, inputs::{Inputs, winit_input::EngineInput}, render::{render_engine::RenderEngine, render_utils}};
pub struct App {
render_engine: RenderEngine,
inputs: Inputs,
$($component: $type,)*
}
impl EngineApp for App {
fn create(mut render_engine: RenderEngine) -> Self {
let inputs = Inputs::new();
$(let $component = <$type>::create(&mut render_engine);)*
Self {
render_engine,
inputs,
$($component,)*
}
}
fn start(&mut self) {
$(
<$type>::start(&mut self.$component, ($(&mut self.$param),*));
)*
}
fn update(&mut self) {
$(
<$type>::update(&mut self.$component, ($(&mut self.$param),*));
)*
let resources = render_utils::prepare_render(&self.render_engine);
let mut resources = if resources.is_ok() { resources.unwrap() } else { return };
$(
{
let pass_id = $pass_idx;
let color_attachment = wgpu::RenderPassColorAttachment {
view: &resources.view,
resolve_target: None,
ops: if pass_id == 0 {
wgpu::Operations {
load: wgpu::LoadOp::Clear($color),
store: wgpu::StoreOp::Store,
}
} else {
wgpu::Operations {
load: wgpu::LoadOp::Load,
store: wgpu::StoreOp::Store,
}
},
};
let mut pass = resources.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[Some(color_attachment)],
depth_stencil_attachment:
if !$depth { None }
else {
Some(wgpu::RenderPassDepthStencilAttachment {
view: &self.render_engine.depth_texture.view,
depth_ops: Some(wgpu::Operations {
load: wgpu::LoadOp::Clear(1.0),
store: wgpu::StoreOp::Store
}),
stencil_ops: None
})
},
occlusion_query_set: None,
timestamp_writes: None,
});
$(
self.render_engine.pipeline_path($pipeline).unwrap().bind(&mut pass);
$(
self.$prepare.render(&self.render_engine, &mut pass);
)*
self.$to_render.render(&self.render_engine, &mut pass);
)*
}
)*
render_utils::finalize_render(&mut self.render_engine, resources);
self.render_engine.next_frame();
self.inputs.reset();
}
fn input(&mut self, input: EngineInput) {
self.inputs.handle_input(input);
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) { self.render_engine.resize(new_size); }
fn exit(&mut self) {
$(
<$type>::exit(&mut self.$component, ($(&mut self.$param),*));
)*
}
}
};
}