ltn/render/
filters.rs
1use std::collections::BTreeMap;
2
3use geom::Angle;
4use map_model::{FilterType, Map};
5use widgetry::mapspace::{DrawCustomUnzoomedShapes, PerZoom};
6use widgetry::{EventCtx, GeomBatch, RewriteColor};
7
8use crate::render;
9
10pub fn render_modal_filters(ctx: &EventCtx, map: &Map) -> render::Toggle3Zoomed {
11 let mut batch = GeomBatch::new();
12 let mut low_zoom = DrawCustomUnzoomedShapes::builder();
13
14 let mut icons = BTreeMap::new();
15 for ft in [
16 FilterType::NoEntry,
17 FilterType::WalkCycleOnly,
18 FilterType::BusGate,
19 FilterType::SchoolStreet,
20 ] {
21 icons.insert(ft, GeomBatch::load_svg(ctx, render::filter_svg_path(ft)));
22 }
23
24 for (road, filter) in map.all_roads_with_modal_filter() {
25 let icon = &icons[&filter.filter_type];
26 let rewrite_color = if map.get_edits().is_filter_modified(road.id, filter) {
27 RewriteColor::NoOp
28 } else {
29 RewriteColor::ChangeAlpha(0.7)
30 };
31
32 if let Ok((pt, road_angle)) = road.center_pts.dist_along(filter.dist) {
33 let angle = if filter.filter_type == FilterType::NoEntry {
34 road_angle.rotate_degs(90.0)
35 } else {
36 Angle::ZERO
37 };
38
39 batch.append(
40 icon.clone()
41 .scale_to_fit_width(road.get_width().inner_meters())
42 .centered_on(pt)
43 .rotate(angle)
44 .color(rewrite_color),
45 );
46
47 let icon = icon.clone();
49 low_zoom.add_custom(Box::new(move |batch, thickness| {
51 batch.append(
52 icon.clone()
53 .scale_to_fit_width(30.0 * thickness)
54 .centered_on(pt)
55 .rotate(angle)
56 .color(rewrite_color),
57 );
58 }));
59 }
60 }
61
62 for i in map.all_intersections() {
63 if let Some(ref filter) = i.modal_filter {
64 let icon = &icons[&filter.filter_type];
65 let rewrite_color = if map.get_edits().is_diagonal_filter_modified(i.id, filter) {
66 RewriteColor::NoOp
67 } else {
68 RewriteColor::ChangeAlpha(0.7)
69 };
70
71 let line = filter.geometry(map);
72 let angle = if filter.filter_type == FilterType::NoEntry {
73 line.angle()
74 } else {
75 Angle::ZERO
76 };
77 let pt = line.middle().unwrap();
78
79 batch.append(
80 icon.clone()
81 .scale_to_fit_width(line.length().inner_meters())
82 .centered_on(pt)
83 .rotate(angle)
84 .color(rewrite_color),
85 );
86
87 let icon = icon.clone();
88 low_zoom.add_custom(Box::new(move |batch, thickness| {
89 batch.append(
91 icon.clone()
92 .scale(0.4 * thickness)
93 .centered_on(pt)
94 .rotate(angle)
95 .color(rewrite_color),
96 );
97 }));
98 }
99 }
100
101 let min_zoom_for_detail = 5.0;
102 let step_size = 0.1;
103 render::Toggle3Zoomed::new(
106 batch.build(ctx),
107 low_zoom.build(PerZoom::new(min_zoom_for_detail, step_size)),
108 )
109}