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_app::{PluginGroupBuilder, prelude::*};
13use bevy_asset::prelude::*;
14use bevy_ecs::prelude::*;
15use bevy_render::{
16 Render, RenderApp, RenderSet,
17 prelude::*,
18 render_phase::AddRenderCommand,
19 render_resource::SpecializedRenderPipelines,
20 sync_component::SyncComponentPlugin,
21 view::{ExtractedView, VisibilitySystems},
22};
23pub use bytemuck;
24use hephae_utils::prelude::*;
25
26use crate::{
27 drawer::{Drawer, HasDrawer, extract_drawers, queue_drawers},
28 image_bind::{ImageAssetEvents, ImageBindGroups, extract_image_events, validate_image_bind_groups},
29 pipeline::{
30 DrawBuffers, DrawRequests, VertexPipeline, ViewBatches, ViewIndexBuffer, VisibleDrawers, extract_shader,
31 load_shader, prepare_indices, prepare_view_bind_groups, queue_vertices,
32 },
33 prelude::Vertex,
34 vertex::{DrawItems, VertexDrawers, check_visibilities},
35};
36
37pub mod prelude {
39 pub use ::bytemuck::{self, NoUninit, Pod, Zeroable};
40
41 pub use crate::{
42 HephaeRenderSystems,
43 attribute::{IsVertexAttribute, LinearRgbaExt as _, Nor, VertexLayout},
44 drawer::{Drawer, DrawerExtract, HasDrawer, VertexQueuer},
45 image_bind::ImageBindGroups,
46 pipeline::{VertexPipeline, ViewBatches},
47 vertex::Vertex,
48 };
49}
50
51plugin_conf! {
52 pub trait VertexConf for Vertex, T => VertexPlugin::<T>::default()
54}
55
56plugin_conf! {
57 pub trait DrawerConf for Drawer, T => DrawerPlugin::<T>::default()
59}
60
61plugin_def! {
62 pub struct VertexPlugin<T: Vertex>;
68 fn build(&self, app: &mut App) {
69 app.init_resource::<VertexDrawers<T>>()
70 .add_systems(Startup, load_shader::<T>)
71 .add_systems(PostUpdate, check_visibilities::<T>.in_set(VisibilitySystems::CheckVisibility));
72
73 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
74 let world = render_app
75 .init_resource::<SpecializedRenderPipelines<VertexPipeline<T>>>()
76 .add_render_command::<T::Item, DrawRequests<T>>()
77 .add_systems(ExtractSchedule, extract_shader::<T>)
78 .add_systems(Render, queue_vertices::<T>.in_set(HephaeRenderSystems::QueueVertices))
79 .world_mut();
80
81 world.register_required_components::<ExtractedView, ViewBatches<T>>();
82 world.register_required_components::<ExtractedView, ViewIndexBuffer<T>>();
83 world.register_required_components::<ExtractedView, VisibleDrawers<T>>();
84 }
85 }
86
87 fn finish(&self, app: &mut App) {
88 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
89 render_app
90 .init_resource::<DrawBuffers<T>>()
91 .init_resource::<VertexPipeline<T>>()
92 .add_systems(
93 Render,
94 (
95 prepare_indices::<T>.in_set(HephaeRenderSystems::PrepareIndices),
96 prepare_view_bind_groups::<T>.in_set(HephaeRenderSystems::PrepareBindGroups),
97 ),
98 );
99 }
100
101 T::setup(app);
102 }
103}
104
105plugin_def! {
106 pub struct DrawerPlugin<T: Drawer>;
111 fn build(&self, app: &mut App) {
112 app.add_plugins(SyncComponentPlugin::<HasDrawer<T>>::default())
113 .register_type::<HasDrawer<T>>()
114 .world_mut()
115 .resource_scope::<VertexDrawers<T::Vertex>, ()>(|world, mut drawers| drawers.add::<T>(world));
116
117 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
118 render_app
119 .add_systems(ExtractSchedule, extract_drawers::<T>)
120 .add_systems(Render, queue_drawers::<T>.in_set(HephaeRenderSystems::QueueDrawers))
121 .world_mut()
122 .register_required_components::<T, DrawItems<T::Vertex>>();
123 }
124 }
125}
126
127plugin_def! {
128 #[plugin_group]
130 pub struct RendererPlugin<V: VertexConf = (), D: DrawerConf = ()>;
131 fn build(self) -> PluginGroupBuilder {
132 let mut builder = PluginGroupBuilder::start::<Self>().add(|app: &mut App| {
133 app.world_mut().resource_mut::<Assets<Shader>>().insert(
134 &HEPHAE_VIEW_BINDINGS_HANDLE,
135 Shader::from_wgsl(include_str!("view_bindings.wgsl"), "hephae/view_bindings.wgsl"),
136 );
137
138 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
139 render_app
140 .configure_sets(
141 Render,
142 (
143 (
144 HephaeRenderSystems::ClearBatches,
145 HephaeRenderSystems::QueueDrawers,
146 HephaeRenderSystems::QueueVertices,
147 )
148 .in_set(RenderSet::Queue),
149 HephaeRenderSystems::QueueDrawers.before(HephaeRenderSystems::QueueVertices),
150 HephaeRenderSystems::PrepareIndices.in_set(RenderSet::PrepareResources),
151 HephaeRenderSystems::PrepareBindGroups.in_set(RenderSet::PrepareBindGroups),
152 ),
153 )
154 .init_resource::<ImageAssetEvents>()
155 .init_resource::<ImageBindGroups>()
156 .add_systems(ExtractSchedule, extract_image_events)
157 .add_systems(
158 Render,
159 validate_image_bind_groups.before(HephaeRenderSystems::PrepareBindGroups),
160 );
161 }
162 });
163
164 builder = V::build(builder);
165 D::build(builder)
166 }
167}
168
169pub const HEPHAE_VIEW_BINDINGS_HANDLE: Handle<Shader> = Handle::weak_from_u128(278527494526026980866063021704582553601);
172
173#[derive(SystemSet, Debug, Copy, Clone, PartialEq, Eq, Hash)]
175pub enum HephaeRenderSystems {
176 ClearBatches,
178 QueueDrawers,
180 QueueVertices,
182 PrepareIndices,
185 PrepareBindGroups,
187}