use crate::{
components::{
immediate_batch::HaImmediateBatch, material_instance::HaMaterialInstance,
mesh_instance::HaMeshInstance,
},
ha_renderer::HaRenderer,
material::domains::surface::SurfaceDomain,
mesh::{BufferStorage, Mesh, MeshId, MeshReference},
};
use core::ecs::{life_cycle::EntityChanges, Comp, Entity, Universe, WorldRef};
use std::collections::HashMap;
#[derive(Debug, Default)]
pub struct HaImmediateBatchSystemCache {
meshes: HashMap<Entity, MeshId>,
}
pub type HaImmediateBatchSystemResources<'a, V> = (
WorldRef,
&'a mut HaRenderer,
&'a EntityChanges,
&'a mut HaImmediateBatchSystemCache,
Comp<&'a mut HaImmediateBatch<V>>,
Comp<&'a mut HaMeshInstance>,
Comp<&'a HaMaterialInstance>,
);
pub fn ha_immediate_batch_system<V>(universe: &mut Universe)
where
V: SurfaceDomain + Default + Copy + Send + Sync + 'static,
{
let (world, mut renderer, changes, mut cache, ..) =
universe.query_resources::<HaImmediateBatchSystemResources<V>>();
for entity in changes.despawned() {
if let Some(id) = cache.meshes.remove(&entity) {
let _ = renderer.remove_mesh(id);
}
}
for (entity, (batch, mesh)) in world
.query::<(&mut HaImmediateBatch<V>, &mut HaMeshInstance)>()
.with::<&HaMaterialInstance>()
.iter()
{
mesh.reference = MeshReference::None;
if let Ok(factory) = batch.factory.factory() {
if let Some(id) = cache.meshes.get(&entity) {
if let Some(m) = renderer.mesh_mut(*id) {
if factory.write_into(m).is_ok() {
mesh.reference = MeshReference::Id(*id);
}
}
} else {
let mut m = Mesh::new(factory.layout().to_owned());
m.set_regenerate_bounds(false);
m.set_vertex_storage_all(BufferStorage::Dynamic);
m.set_index_storage(BufferStorage::Dynamic);
if factory.write_into(&mut m).is_ok() {
if let Ok(id) = renderer.add_mesh(m) {
mesh.reference = MeshReference::Id(id);
cache.meshes.insert(entity, id);
}
}
}
}
batch.factory.clear();
}
}