use std::iter;
use crate::{
context::MapContext,
coords::ViewRegion,
render::{
eventually::{Eventually, Eventually::Initialized},
shaders::{ShaderFeatureStyle, ShaderLayerMetadata, Vec4f32},
Renderer,
},
style::Style,
tcs::tiles::Tiles,
vector::{
AvailableVectorLayerData, VectorBufferPool, VectorLayerData, VectorLayersDataComponent,
},
};
pub fn upload_system(
MapContext {
world,
style,
view_state,
renderer: Renderer { device, queue, .. },
..
}: &mut MapContext,
) {
let Some(
Initialized(buffer_pool)
) = world.resources.query_mut::<
&mut Eventually<VectorBufferPool>,
>() else { return; };
let view_region = view_state.create_view_region();
if let Some(view_region) = &view_region {
upload_tesselated_layer(
buffer_pool,
device,
queue,
&mut world.tiles,
style,
view_region,
);
}
}
fn upload_tesselated_layer(
buffer_pool: &mut VectorBufferPool,
_device: &wgpu::Device,
queue: &wgpu::Queue,
tiles: &mut Tiles,
style: &Style,
view_region: &ViewRegion,
) {
for coords in view_region.iter() {
let Some(vector_layers) = tiles.query_mut::<&VectorLayersDataComponent>(coords) else { continue; };
let loaded_layers = buffer_pool
.get_loaded_source_layers_at(coords)
.unwrap_or_default();
let available_layers = vector_layers
.layers
.iter()
.flat_map(|data| match data {
VectorLayerData::Available(data) => Some(data),
VectorLayerData::Missing(_) => None,
})
.filter(|data| !loaded_layers.contains(data.source_layer.as_str()))
.collect::<Vec<_>>();
for style_layer in &style.layers {
let source_layer = style_layer.source_layer.as_ref().unwrap();
let Some(AvailableVectorLayerData {
coords,
feature_indices,
buffer,
..
}) = available_layers
.iter()
.find(|layer| source_layer.as_str() == layer.source_layer) else { continue; };
let color: Option<Vec4f32> = style_layer
.paint
.as_ref()
.and_then(|paint| paint.get_color())
.map(|color| color.into());
let feature_metadata = (0..feature_indices.len()) .enumerate()
.flat_map(|(i, _feature)| {
iter::repeat(ShaderFeatureStyle {
color: color.unwrap(),
})
.take(feature_indices[i] as usize)
})
.collect::<Vec<_>>();
log::debug!("Allocating geometry at {}", &coords);
buffer_pool.allocate_layer_geometry(
queue,
*coords,
style_layer.clone(),
buffer,
ShaderLayerMetadata::new(style_layer.index as f32),
&feature_metadata,
);
}
}
}