ltn/render/
filters.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::collections::BTreeMap;

use geom::Angle;
use map_model::{FilterType, Map};
use widgetry::mapspace::{DrawCustomUnzoomedShapes, PerZoom};
use widgetry::{EventCtx, GeomBatch, RewriteColor};

use crate::render;

pub fn render_modal_filters(ctx: &EventCtx, map: &Map) -> render::Toggle3Zoomed {
    let mut batch = GeomBatch::new();
    let mut low_zoom = DrawCustomUnzoomedShapes::builder();

    let mut icons = BTreeMap::new();
    for ft in [
        FilterType::NoEntry,
        FilterType::WalkCycleOnly,
        FilterType::BusGate,
        FilterType::SchoolStreet,
    ] {
        icons.insert(ft, GeomBatch::load_svg(ctx, render::filter_svg_path(ft)));
    }

    for (road, filter) in map.all_roads_with_modal_filter() {
        let icon = &icons[&filter.filter_type];
        let rewrite_color = if map.get_edits().is_filter_modified(road.id, filter) {
            RewriteColor::NoOp
        } else {
            RewriteColor::ChangeAlpha(0.7)
        };

        if let Ok((pt, road_angle)) = road.center_pts.dist_along(filter.dist) {
            let angle = if filter.filter_type == FilterType::NoEntry {
                road_angle.rotate_degs(90.0)
            } else {
                Angle::ZERO
            };

            batch.append(
                icon.clone()
                    .scale_to_fit_width(road.get_width().inner_meters())
                    .centered_on(pt)
                    .rotate(angle)
                    .color(rewrite_color),
            );

            // TODO Memory intensive
            let icon = icon.clone();
            // TODO They can shrink a bit past their map size
            low_zoom.add_custom(Box::new(move |batch, thickness| {
                batch.append(
                    icon.clone()
                        .scale_to_fit_width(30.0 * thickness)
                        .centered_on(pt)
                        .rotate(angle)
                        .color(rewrite_color),
                );
            }));
        }
    }

    for i in map.all_intersections() {
        if let Some(ref filter) = i.modal_filter {
            let icon = &icons[&filter.filter_type];
            let rewrite_color = if map.get_edits().is_diagonal_filter_modified(i.id, filter) {
                RewriteColor::NoOp
            } else {
                RewriteColor::ChangeAlpha(0.7)
            };

            let line = filter.geometry(map);
            let angle = if filter.filter_type == FilterType::NoEntry {
                line.angle()
            } else {
                Angle::ZERO
            };
            let pt = line.middle().unwrap();

            batch.append(
                icon.clone()
                    .scale_to_fit_width(line.length().inner_meters())
                    .centered_on(pt)
                    .rotate(angle)
                    .color(rewrite_color),
            );

            let icon = icon.clone();
            low_zoom.add_custom(Box::new(move |batch, thickness| {
                // TODO Why is this magic value different than the one above?
                batch.append(
                    icon.clone()
                        .scale(0.4 * thickness)
                        .centered_on(pt)
                        .rotate(angle)
                        .color(rewrite_color),
                );
            }));
        }
    }

    let min_zoom_for_detail = 5.0;
    let step_size = 0.1;
    // TODO Ideally we get rid of Toggle3Zoomed and make DrawCustomUnzoomedShapes handle this
    // medium-zoom case.
    render::Toggle3Zoomed::new(
        batch.build(ctx),
        low_zoom.build(PerZoom::new(min_zoom_for_detail, step_size)),
    )
}