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
110
111
112
113
114
115
116
117
118
119
120
use geom::Distance;
use map_model::PathConstraints;
use raw_map::{Direction, DrivingSide, LaneSpec, LaneType};
use widgetry::mapspace::{World, WorldOutcome};
use widgetry::{EventCtx, Image, Text, TextExt, Widget};
use super::Obj;
use crate::{colors, App, Neighbourhood};
pub fn widget(ctx: &mut EventCtx) -> Widget {
Widget::col(vec![
Widget::row(vec![
Image::from_path("system/assets/tools/pencil.svg")
.into_widget(ctx)
.centered_vert(),
"Click a road to change its direction".text_widget(ctx),
]),
])
}
pub fn make_world(ctx: &mut EventCtx, app: &App, neighbourhood: &Neighbourhood) -> World<Obj> {
let map = &app.map;
let mut world = World::bounded(map.get_bounds());
for r in &neighbourhood.orig_perimeter.interior {
let road = map.get_r(*r);
if !PathConstraints::Car.can_use_road(road, map) {
continue;
}
world
.add(Obj::InteriorRoad(*r))
.hitbox(road.get_thick_polygon())
.drawn_in_master_batch()
.hover_outline(colors::OUTLINE, Distance::meters(5.0))
.tooltip(Text::from(format!(
"Click to flip direction of {}",
road.get_name(app.opts.language.as_ref()),
)))
.clickable()
.build(ctx);
}
world.initialize_hover(ctx);
world
}
pub fn handle_world_outcome(ctx: &mut EventCtx, app: &mut App, outcome: WorldOutcome<Obj>) -> bool {
match outcome {
WorldOutcome::ClickedObject(Obj::InteriorRoad(r)) => {
let leftmost_dir = if app.map.get_config().driving_side == DrivingSide::Right {
Direction::Back
} else {
Direction::Fwd
};
let mut edits = app.map.get_edits().clone();
edits.commands.push(app.map.edit_road_cmd(r, |new| {
let oneway_dir = LaneSpec::oneway_for_driving(&new.lanes_ltr);
let num_driving_lanes = new
.lanes_ltr
.iter()
.filter(|lane| lane.lt == LaneType::Driving)
.count();
let mut driving_lanes_so_far = 0;
for lane in &mut new.lanes_ltr {
if lane.lt == LaneType::Driving {
driving_lanes_so_far += 1;
match oneway_dir {
Some(Direction::Fwd) => {
lane.dir = Direction::Back;
}
Some(Direction::Back) => {
if num_driving_lanes == 1 {
lane.dir = Direction::Fwd;
} else {
if (driving_lanes_so_far as f64) / (num_driving_lanes as f64)
<= 0.5
{
lane.dir = leftmost_dir;
} else {
lane.dir = leftmost_dir.opposite();
}
}
}
None => {
lane.dir = Direction::Fwd;
}
}
}
}
}));
ctx.loading_screen("apply edits", |_, timer| {
let effects = app.map.must_apply_edits(edits, timer);
for r in effects.changed_roads {
let road = app.map.get_r(r);
app.draw_map.recreate_road(road, &app.map);
}
for i in effects.changed_intersections {
app.draw_map.recreate_intersection(i, &app.map);
}
app.map.keep_pathfinder_despite_edits();
});
true
}
_ => false,
}
}