1use crate::{
2 render_resource::{encase::internal::WriteInto, DynamicUniformBuffer, ShaderType},
3 renderer::{RenderDevice, RenderQueue},
4 GpuResourceAppExt, Render, RenderApp, RenderSystems,
5};
6use bevy_app::{App, Plugin};
7use bevy_ecs::{component::Component, prelude::*};
8use core::{marker::PhantomData, ops::Deref};
9
10#[derive(impl<C: Component> bevy_ecs::component::Component for DynamicUniformIndex<C>
where Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component)]
12pub struct DynamicUniformIndex<C: Component> {
13 index: u32,
14 marker: PhantomData<C>,
15}
16
17impl<C: Component> DynamicUniformIndex<C> {
18 #[inline]
19 pub fn index(&self) -> u32 {
20 self.index
21 }
22}
23
24pub struct UniformComponentPlugin<C>(PhantomData<fn() -> C>);
34
35impl<C> Default for UniformComponentPlugin<C> {
36 fn default() -> Self {
37 Self(PhantomData)
38 }
39}
40
41impl<C: Component + ShaderType + WriteInto + Clone> Plugin for UniformComponentPlugin<C> {
42 fn build(&self, app: &mut App) {
43 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
44 render_app
45 .init_gpu_resource::<ComponentUniforms<C>>()
46 .add_systems(
47 Render,
48 prepare_uniform_components::<C>.in_set(RenderSystems::PrepareResources),
49 );
50 }
51 }
52}
53
54#[derive(impl<C: Component + ShaderType> bevy_ecs::component::Component for
ComponentUniforms<C> where Self: ::core::marker::Send +
::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::SparseSet;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {
let resource_component_id =
if let ::core::option::Option::Some(id) =
required_components.components_registrator().component_id::<ComponentUniforms<C>>()
{
id
} else {
required_components.components_registrator().register_component::<ComponentUniforms<C>>()
};
required_components.register_required::<bevy_ecs::resource::IsResource>(move
||
bevy_ecs::resource::IsResource::new(resource_component_id));
}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}
impl<C: Component + ShaderType> bevy_ecs::resource::Resource for
ComponentUniforms<C> where Self: ::core::marker::Send +
::core::marker::Sync + 'static {}Resource)]
56pub struct ComponentUniforms<C: Component + ShaderType> {
57 uniforms: DynamicUniformBuffer<C>,
58}
59
60impl<C: Component + ShaderType> Deref for ComponentUniforms<C> {
61 type Target = DynamicUniformBuffer<C>;
62
63 #[inline]
64 fn deref(&self) -> &Self::Target {
65 &self.uniforms
66 }
67}
68
69impl<C: Component + ShaderType> ComponentUniforms<C> {
70 #[inline]
71 pub fn uniforms(&self) -> &DynamicUniformBuffer<C> {
72 &self.uniforms
73 }
74}
75
76impl<C: Component + ShaderType> Default for ComponentUniforms<C> {
77 fn default() -> Self {
78 let mut uniforms = DynamicUniformBuffer::default();
79 uniforms.set_label(Some(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} ComponentUniforms buffer",
core::any::type_name::<C>()))
})format!(
80 "{} ComponentUniforms buffer",
81 core::any::type_name::<C>()
82 )));
83 Self { uniforms }
84 }
85}
86
87fn prepare_uniform_components<C>(
90 mut commands: Commands,
91 render_device: Res<RenderDevice>,
92 render_queue: Res<RenderQueue>,
93 mut component_uniforms: ResMut<ComponentUniforms<C>>,
94 components: Query<(Entity, &C)>,
95) where
96 C: Component + ShaderType + WriteInto + Clone,
97{
98 let components_iter = components.iter();
99 let count = components_iter.len();
100 let Some(mut writer) =
101 component_uniforms
102 .uniforms
103 .get_writer(count, &render_device, &render_queue)
104 else {
105 return;
106 };
107 let entities = components_iter
108 .map(|(entity, component)| {
109 (
110 entity,
111 DynamicUniformIndex::<C> {
112 index: writer.write(component),
113 marker: PhantomData,
114 },
115 )
116 })
117 .collect::<Vec<_>>();
118 commands.try_insert_batch(entities);
119}