rustial_engine/map_state/
heavy_layers.rs1use super::*;
2
3impl MapState {
4 pub(super) fn refresh_streamed_vector_layer_features(&mut self) -> HashMap<String, bool> {
5 let streamed_layers: Vec<StreamedVectorLayerRefreshSpec> = self
6 .layers
7 .iter()
8 .filter_map(|layer| {
9 let vector_layer = layer
10 .as_any()
11 .downcast_ref::<crate::layers::VectorLayer>()?;
12 let source_id = vector_layer.query_source_id.as_ref()?;
13 let runtime = self.streamed_vector_sources.get(source_id)?;
14 let layer_key = vector_layer
15 .query_layer_id
16 .as_deref()
17 .unwrap_or(vector_layer.name())
18 .to_owned();
19 Some(StreamedVectorLayerRefreshSpec {
20 runtime_id: layer.id(),
21 layer_key,
22 source_id: source_id.clone(),
23 source_layer: vector_layer.query_source_layer.clone(),
24 visible_tiles: runtime.visible_tiles().tiles.clone(),
25 })
26 })
27 .collect();
28
29 let resolved = resolve_streamed_vector_layer_refresh(streamed_layers);
30
31 let mut changed = HashMap::new();
32 let active_keys: HashSet<String> = resolved
33 .iter()
34 .map(|entry| entry.layer_key.clone())
35 .collect();
36 self.streamed_vector_layer_fingerprints
37 .retain(|key, _| active_keys.contains(key));
38 self.streamed_vector_query_payloads
39 .retain(|key, _| active_keys.contains(key));
40
41 for resolved_layer in resolved {
42 let was_changed = self
43 .streamed_vector_layer_fingerprints
44 .get(&resolved_layer.layer_key)
45 .copied()
46 != Some(resolved_layer.fingerprint);
47 self.streamed_vector_layer_fingerprints
48 .insert(resolved_layer.layer_key.clone(), resolved_layer.fingerprint);
49 let (features, provenance) = resolved_layer.rebuild_feature_inputs();
50 self.streamed_vector_query_payloads.insert(
51 resolved_layer.layer_key.clone(),
52 resolved_layer.tile_payloads,
53 );
54
55 if let Some(layer) = self
56 .layers
57 .iter_mut()
58 .find(|layer| layer.id() == resolved_layer.runtime_id)
59 {
60 if let Some(vector_layer) = layer
61 .as_any_mut()
62 .downcast_mut::<crate::layers::VectorLayer>()
63 {
64 vector_layer.set_features_with_provenance(features, provenance);
65 }
66 }
67
68 changed.insert(resolved_layer.layer_key, was_changed);
69 }
70
71 changed
72 }
73
74 pub(super) fn rebuild_symbol_query_payloads(&mut self) {
75 let view = VisiblePlacedSymbolView::new(&self.placed_symbols);
76 self.streamed_symbol_query_payloads = view.rebuild_query_payloads();
77 self.streamed_symbol_dependency_payloads = view.rebuild_dependency_payloads();
78 }
79
80 pub(super) fn streamed_payload_view_for(&self, layer_id: &str) -> StreamedPayloadView<'_> {
85 StreamedPayloadView::from_optional(
86 self.streamed_vector_query_payloads
87 .get(layer_id)
88 .map(Vec::as_slice),
89 )
90 }
91
92 pub(super) fn streamed_symbol_query_payloads_for(
98 &self,
99 layer_id: &str,
100 ) -> &[SymbolQueryPayload] {
101 symbol_query_payloads_from_optional(
102 self.streamed_symbol_query_payloads
103 .get(layer_id)
104 .map(Vec::as_slice),
105 )
106 }
107
108 pub(super) fn invalidate_symbol_dependency_tiles(
109 &mut self,
110 matches: impl Fn(&crate::symbols::SymbolAssetDependencies) -> bool,
111 ) -> usize {
112 let affected: HashSet<StreamedSymbolPayloadKey> =
113 collect_affected_symbol_payloads(&self.streamed_symbol_dependency_payloads, matches);
114
115 if affected.is_empty() {
116 return 0;
117 }
118
119 for (layer_id, tile) in &affected {
120 if let Some(tile) = tile {
121 self.dirty_streamed_symbol_tiles
122 .entry(layer_id.clone())
123 .or_default()
124 .insert(*tile);
125 } else {
126 self.dirty_streamed_symbol_layers.insert(layer_id.clone());
127 }
128 }
129 self.data_update_elapsed = self.data_update_interval;
130
131 self.placed_symbols = Arc::new(prune_affected_symbol_payloads(
132 &affected,
133 &self.placed_symbols,
134 &mut self.streamed_symbol_query_payloads,
135 &mut self.streamed_symbol_dependency_payloads,
136 ));
137 self.symbol_assets
138 .rebuild_from_symbols(&self.placed_symbols);
139 affected.len()
140 }
141
142 pub(super) fn update_heavy_layers(&mut self, dt_seconds: f64) {
148 use crate::layer::LayerKind;
149 use crate::layers::{VectorLayer, VectorRenderMode};
150
151 if let Some(terrain_tiles) = self.desired_terrain_tiles() {
158 self.update_terrain_with_tiles(&terrain_tiles);
159 } else {
160 self.update_terrain();
161 }
162
163 let camera_projection = self.camera.projection();
167 let mut all_vectors: Vec<VectorMeshData> = Vec::new();
168 let mut symbol_candidates = Vec::new();
169 let mut had_symbol_layer = false;
170 let mut active_keys: HashSet<SyncVectorCacheKey> = HashSet::new();
171
172 self.refresh_streamed_vector_layer_features();
173
174 for layer in self.layers.iter() {
175 if !layer.visible() || layer.kind() != LayerKind::Vector {
176 continue;
177 }
178 if let Some(vector_layer) = layer.as_any().downcast_ref::<VectorLayer>() {
179 let layer_id = vector_layer
180 .query_layer_id
181 .as_deref()
182 .unwrap_or(vector_layer.name());
183 let is_streamed_layer = vector_layer
184 .query_source_id
185 .as_ref()
186 .is_some_and(|source_id| self.streamed_vector_sources.contains_key(source_id));
187 had_symbol_layer =
188 had_symbol_layer || vector_layer.style.render_mode == VectorRenderMode::Symbol;
189
190 let cache_key = SyncVectorCacheKey {
193 layer_id: vector_layer.id(),
194 style_fingerprint: vector_layer.style.tessellation_fingerprint(),
195 data_generation: vector_layer.data_generation(),
196 projection: camera_projection,
197 };
198 active_keys.insert(cache_key);
199
200 if let Some(entry) = self.sync_vector_cache.get(&cache_key) {
202 if !entry.mesh.is_empty() {
203 all_vectors.push(entry.mesh.clone());
204 }
205 } else {
206 let mesh = vector_layer.tessellate(camera_projection);
208 if !mesh.is_empty() {
209 all_vectors.push(mesh.clone());
210 }
211 self.sync_vector_cache
212 .insert(cache_key, SyncVectorCacheEntry { mesh });
213 }
214
215 if is_streamed_layer {
216 let streamed_payloads = self.streamed_payload_view_for(layer_id);
217 let (features, provenance) = streamed_payloads.rebuild_feature_inputs();
218 symbol_candidates.extend(
219 vector_layer.symbol_candidates_for_features(&features, &provenance),
220 );
221 } else {
222 symbol_candidates.extend(vector_layer.symbol_candidates());
223 }
224 }
225 }
226
227 self.sync_vector_cache
230 .retain(|key, _| active_keys.contains(key));
231 self.vector_meshes = Arc::new(all_vectors);
232
233 if had_symbol_layer && !symbol_candidates.is_empty() {
235 let meters_per_pixel = self.camera.meters_per_pixel();
236 let placed = self.symbol_placement.place_candidates(
237 &symbol_candidates,
238 camera_projection,
239 meters_per_pixel,
240 dt_seconds,
241 Some(&self.scene_viewport_bounds),
242 );
243 self.symbol_assets.rebuild_from_symbols(&placed);
244 self.placed_symbols = Arc::new(placed);
245 self.rebuild_symbol_query_payloads();
246 } else if !had_symbol_layer {
247 self.placed_symbols = Arc::new(Vec::new());
248 self.streamed_symbol_query_payloads.clear();
249 self.streamed_symbol_dependency_payloads.clear();
250 self.dirty_streamed_symbol_tiles.clear();
251 }
252
253 let mut models = Vec::new();
255 for layer in self.layers.iter() {
256 if !layer.visible() || layer.kind() != LayerKind::Model {
257 continue;
258 }
259 if let Some(model_layer) = layer.as_any().downcast_ref::<crate::layers::ModelLayer>() {
260 models.extend(model_layer.instances.iter().cloned());
261 }
262 }
263 self.model_instances = Arc::new(models);
264
265 self.collect_visualization_overlays();
267
268 self.collect_image_overlays();
270
271 self.dirty_streamed_symbol_layers.clear();
272 self.dirty_streamed_symbol_tiles.clear();
273 }
274
275 pub(super) fn apply_pending_frame_overrides(&mut self) {
276 if let Some(meshes) = self.pending_terrain_meshes.take() {
277 self.terrain_meshes = meshes;
278 }
279
280 if let Some(meshes) = self.pending_vector_meshes.take() {
281 self.vector_meshes = meshes;
282 }
283
284 if let Some(instances) = self.pending_model_instances.take() {
285 self.model_instances = instances;
286 }
287 }
288
289 pub(super) fn collect_visualization_overlays(&mut self) {
291 use crate::visualization::{
292 GridExtrusionLayer, GridScalarLayer, InstancedColumnLayer, PointCloudLayer,
293 VisualizationOverlay,
294 };
295
296 let mut overlays = Vec::new();
297 for layer in self.layers.iter() {
298 if !layer.visible() {
299 continue;
300 }
301 if layer.kind() != crate::layer::LayerKind::Visualization {
302 continue;
303 }
304 if let Some(grid_layer) = layer.as_any().downcast_ref::<GridScalarLayer>() {
305 overlays.push(VisualizationOverlay::GridScalar {
306 layer_id: grid_layer.id(),
307 grid: grid_layer.grid.clone(),
308 field: grid_layer.field.clone(),
309 ramp: grid_layer.ramp.clone(),
310 });
311 } else if let Some(grid_layer) = layer.as_any().downcast_ref::<GridExtrusionLayer>() {
312 overlays.push(VisualizationOverlay::GridExtrusion {
313 layer_id: grid_layer.id(),
314 grid: grid_layer.grid.clone(),
315 field: grid_layer.field.clone(),
316 ramp: grid_layer.ramp.clone(),
317 params: grid_layer.params.clone(),
318 });
319 } else if let Some(col_layer) = layer.as_any().downcast_ref::<InstancedColumnLayer>() {
320 overlays.push(VisualizationOverlay::Columns {
321 layer_id: col_layer.id(),
322 columns: col_layer.columns.clone(),
323 ramp: col_layer.ramp.clone(),
324 });
325 } else if let Some(point_layer) = layer.as_any().downcast_ref::<PointCloudLayer>() {
326 overlays.push(VisualizationOverlay::Points {
327 layer_id: point_layer.id(),
328 points: point_layer.points.clone(),
329 ramp: point_layer.ramp.clone(),
330 });
331 }
332 }
333 self.visualization_overlays = Arc::new(overlays);
334 }
335
336 pub(super) fn collect_image_overlays(&mut self) {
338 use crate::layers::DynamicImageOverlayLayer;
339 use crate::layers::ImageOverlayLayer;
340
341 let projection = self.camera.projection();
342 let mut overlays = Vec::new();
343 for layer in self.layers.iter_mut() {
344 if !layer.visible() {
345 continue;
346 }
347 if let Some(img_layer) = layer.as_any().downcast_ref::<ImageOverlayLayer>() {
348 overlays.push(img_layer.to_overlay_data(projection));
349 } else if let Some(dyn_layer) = layer
350 .as_any_mut()
351 .downcast_mut::<DynamicImageOverlayLayer>()
352 {
353 dyn_layer.poll_frame();
354 if let Some(data) = dyn_layer.to_overlay_data(projection) {
355 overlays.push(data);
356 }
357 }
358 }
359 self.image_overlays = Arc::new(overlays);
360 }
361
362 pub(super) fn apply_style_document(
364 &mut self,
365 document: &StyleDocument,
366 ) -> Result<(), StyleError> {
367 let layers = document.to_runtime_layers()?;
368 self.layers = LayerStack::new();
369 for layer in layers {
370 self.layers.push(layer);
371 }
372 self.streamed_vector_sources = build_streamed_vector_sources(document);
373 self.streamed_vector_layer_fingerprints.clear();
374 self.streamed_vector_query_payloads.clear();
375 self.streamed_symbol_query_payloads.clear();
376 self.streamed_symbol_dependency_payloads.clear();
377 self.dirty_streamed_symbol_layers.clear();
378 self.dirty_streamed_symbol_tiles.clear();
379 Ok(())
380 }
381}
382
383impl MapState {
384 pub fn style_source_is_used(&self, source_id: &str) -> bool {
386 match self.style_document() {
387 Some(document) => document.source_is_used(source_id),
388 None => false,
389 }
390 }
391
392 pub fn style_layer_ids_using_source(&self, source_id: &str) -> Vec<&str> {
394 match self.style_document() {
395 Some(document) => document.layer_ids_using_source(source_id),
396 None => Vec::new(),
397 }
398 }
399
400 pub fn reload_style_source(
402 &mut self,
403 source_id: impl Into<String>,
404 source: crate::style::StyleSource,
405 ) -> Result<bool, StyleError> {
406 let Some(mut style): Option<MapStyle> = self.style.take() else {
407 return Ok(false);
408 };
409 style.document_mut().set_source(source_id.into(), source);
410 self.apply_style_document(style.document())?;
411 self.style = Some(style);
412 Ok(true)
413 }
414
415 pub fn clear_style_source(
417 &mut self,
418 source_id: &str,
419 ) -> Result<Option<crate::style::StyleSource>, StyleError> {
420 let Some(mut style): Option<MapStyle> = self.style.take() else {
421 return Ok(None);
422 };
423 let removed = style.document_mut().remove_source(source_id);
424 self.apply_style_document(style.document())?;
425 self.style = Some(style);
426 Ok(removed)
427 }
428}
429
430fn build_streamed_vector_sources(
431 document: &StyleDocument,
432) -> HashMap<String, crate::layers::TileLayer> {
433 document
434 .sources()
435 .filter_map(|(source_id, source)| match source {
436 crate::style::StyleSource::VectorTile(vector_source) => {
437 vector_source.make_tile_source().map(|tile_source| {
438 (
439 source_id.to_owned(),
440 crate::layers::TileLayer::new_with_selection_config(
441 format!("__vector_source::{source_id}"),
442 tile_source,
443 vector_source.cache_capacity,
444 vector_source.selection.clone(),
445 ),
446 )
447 })
448 }
449 _ => None,
450 })
451 .collect()
452}
453
454pub(super) fn wrapped_world_delta(delta: f64) -> f64 {
455 let half_world = WGS84_CIRCUMFERENCE * 0.5;
456 if delta > half_world {
457 delta - WGS84_CIRCUMFERENCE
458 } else if delta < -half_world {
459 delta + WGS84_CIRCUMFERENCE
460 } else {
461 delta
462 }
463}
464
465pub(super) fn translated_world_bounds(bounds: &WorldBounds, delta: glam::DVec2) -> WorldBounds {
466 WorldBounds::new(
467 WorldCoord::new(
468 bounds.min.position.x + delta.x,
469 bounds.min.position.y + delta.y,
470 bounds.min.position.z,
471 ),
472 WorldCoord::new(
473 bounds.max.position.x + delta.x,
474 bounds.max.position.y + delta.y,
475 bounds.max.position.z,
476 ),
477 )
478}