1#![allow(internal_features)]
2#![cfg_attr(any(docsrs, docsrs_dep), feature(rustdoc_internals))]
3#![doc = include_str!("../README.md")]
4#![cfg_attr(doc, deny(missing_docs))]
5
6pub mod attribute;
7pub mod drawer;
8pub mod image_bind;
9pub mod pipeline;
10pub mod vertex;
11
12use bevy_asset::prelude::*;
13use bevy_ecs::prelude::*;
14use bevy_render::prelude::*;
15pub use bytemuck;
16
17pub mod prelude {
19 pub use ::bytemuck::{self, NoUninit, Pod, Zeroable};
20
21 pub use crate::{
22 HephaeRenderSystems,
23 attribute::{IsVertexAttribute, LinearRgbaExt as _, Nor, VertexLayout},
24 drawer::{Drawer, DrawerExtract, HasDrawer, VertexQueuer},
25 image_bind::ImageBindGroups,
26 pipeline::{VertexPipeline, ViewBatches},
27 vertex::Vertex,
28 };
29}
30
31pub mod plugin {
33 use std::marker::PhantomData;
34
35 use bevy_app::{PluginGroupBuilder, prelude::*};
36 use bevy_asset::prelude::*;
37 use bevy_ecs::prelude::*;
38 use bevy_render::{
39 Render, RenderApp, RenderSet,
40 prelude::*,
41 render_phase::AddRenderCommand,
42 render_resource::SpecializedRenderPipelines,
43 sync_component::SyncComponentPlugin,
44 view::{ExtractedView, VisibilitySystems},
45 };
46 use hephae_utils::prelude::*;
47
48 use crate::{
49 HEPHAE_VIEW_BINDINGS_HANDLE, HephaeRenderSystems,
50 drawer::{Drawer, HasDrawer, extract_drawers, queue_drawers},
51 image_bind::{ImageAssetEvents, ImageBindGroups, extract_image_events, validate_image_bind_groups},
52 pipeline::{
53 DrawBuffers, DrawRequests, VertexPipeline, ViewBatches, ViewIndexBuffer, VisibleDrawers, extract_shader,
54 load_shader, prepare_indices, prepare_view_bind_groups, queue_vertices,
55 },
56 vertex::{DrawItems, Vertex, VertexDrawers, check_visibilities},
57 };
58
59 plugin_conf! {
60 pub trait VertexConf for Vertex, T => vertex::<T>()
62 }
63
64 plugin_conf! {
65 pub trait DrawerConf for Drawer, T => drawer::<T>()
67 }
68
69 pub fn render<V: VertexConf, D: DrawerConf>() -> impl PluginGroup {
71 struct RenderGroup<V: VertexConf, D: DrawerConf>(PhantomData<(V, D)>);
72 impl<V: VertexConf, D: DrawerConf> PluginGroup for RenderGroup<V, D> {
73 fn build(self) -> PluginGroupBuilder {
74 let mut builder = PluginGroupBuilder::start::<Self>().add(|app: &mut App| {
75 app.world_mut().resource_mut::<Assets<Shader>>().insert(
76 &HEPHAE_VIEW_BINDINGS_HANDLE,
77 Shader::from_wgsl(include_str!("view_bindings.wgsl"), "hephae/view_bindings.wgsl"),
78 );
79
80 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
81 render_app
82 .configure_sets(
83 Render,
84 (
85 (
86 HephaeRenderSystems::ClearBatches,
87 HephaeRenderSystems::QueueDrawers,
88 HephaeRenderSystems::QueueVertices,
89 )
90 .in_set(RenderSet::Queue),
91 HephaeRenderSystems::QueueDrawers.before(HephaeRenderSystems::QueueVertices),
92 HephaeRenderSystems::PrepareIndices.in_set(RenderSet::PrepareResources),
93 HephaeRenderSystems::PrepareBindGroups.in_set(RenderSet::PrepareBindGroups),
94 ),
95 )
96 .init_resource::<ImageAssetEvents>()
97 .init_resource::<ImageBindGroups>()
98 .add_systems(ExtractSchedule, extract_image_events)
99 .add_systems(
100 Render,
101 validate_image_bind_groups.before(HephaeRenderSystems::PrepareBindGroups),
102 );
103 }
104 });
105
106 builder = V::build(builder);
107 D::build(builder)
108 }
109 }
110
111 RenderGroup::<V, D>(PhantomData)
112 }
113
114 pub fn vertex<T: Vertex>() -> impl Plugin {
120 struct VertexPlugin<T: Vertex>(PhantomData<T>);
121 impl<T: Vertex> Plugin for VertexPlugin<T> {
122 fn build(&self, app: &mut App) {
123 app.init_resource::<VertexDrawers<T>>()
124 .add_systems(Startup, load_shader::<T>)
125 .add_systems(PostUpdate, check_visibilities::<T>.in_set(VisibilitySystems::CheckVisibility));
126
127 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
128 let world = render_app
129 .init_resource::<SpecializedRenderPipelines<VertexPipeline<T>>>()
130 .add_render_command::<T::Item, DrawRequests<T>>()
131 .add_systems(ExtractSchedule, extract_shader::<T>)
132 .add_systems(Render, queue_vertices::<T>.in_set(HephaeRenderSystems::QueueVertices))
133 .world_mut();
134
135 world.register_required_components::<ExtractedView, ViewBatches<T>>();
136 world.register_required_components::<ExtractedView, ViewIndexBuffer<T>>();
137 world.register_required_components::<ExtractedView, VisibleDrawers<T>>();
138 }
139 }
140
141 fn finish(&self, app: &mut App) {
142 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
143 render_app
144 .init_resource::<DrawBuffers<T>>()
145 .init_resource::<VertexPipeline<T>>()
146 .add_systems(
147 Render,
148 (
149 prepare_indices::<T>.in_set(HephaeRenderSystems::PrepareIndices),
150 prepare_view_bind_groups::<T>.in_set(HephaeRenderSystems::PrepareBindGroups),
151 ),
152 );
153 }
154
155 T::setup(app);
156 }
157 }
158
159 VertexPlugin::<T>(PhantomData)
160 }
161
162 pub fn drawer<T: Drawer>() -> impl Plugin {
167 |app: &mut App| {
168 app.add_plugins(SyncComponentPlugin::<HasDrawer<T>>::default())
169 .register_type::<HasDrawer<T>>()
170 .world_mut()
171 .resource_scope::<VertexDrawers<T::Vertex>, ()>(|world, mut drawers| drawers.add::<T>(world));
172
173 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
174 render_app
175 .add_systems(ExtractSchedule, extract_drawers::<T>)
176 .add_systems(Render, queue_drawers::<T>.in_set(HephaeRenderSystems::QueueDrawers))
177 .world_mut()
178 .register_required_components::<T, DrawItems<T::Vertex>>();
179 }
180 }
181 }
182}
183
184pub const HEPHAE_VIEW_BINDINGS_HANDLE: Handle<Shader> = Handle::weak_from_u128(278527494526026980866063021704582553601);
187
188#[derive(SystemSet, Debug, Copy, Clone, PartialEq, Eq, Hash)]
190pub enum HephaeRenderSystems {
191 ClearBatches,
193 QueueDrawers,
195 QueueVertices,
197 PrepareIndices,
200 PrepareBindGroups,
203}