mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 16:36:02 +03:00
tool to bulk edit lane types
This commit is contained in:
parent
e54792b883
commit
2d638eb94b
@ -16,7 +16,9 @@ use ezgui::{
|
||||
hotkey, lctrl, Color, EventCtx, EventLoopMode, GfxCtx, Key, ModalMenu, Text, Wizard,
|
||||
WrappedWizard,
|
||||
};
|
||||
use map_model::{IntersectionID, Lane, LaneID, LaneType, Map, MapEdits, Road, TurnID, TurnType};
|
||||
use map_model::{
|
||||
IntersectionID, Lane, LaneID, LaneType, Map, MapEdits, Road, RoadID, TurnID, TurnType,
|
||||
};
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
|
||||
pub enum EditMode {
|
||||
@ -25,6 +27,7 @@ pub enum EditMode {
|
||||
Loading(Wizard),
|
||||
EditingStopSign(stop_signs::StopSignEditor),
|
||||
EditingTrafficSignal(traffic_signals::TrafficSignalEditor),
|
||||
BulkEditLanes(RoadID, Wizard),
|
||||
}
|
||||
|
||||
impl EditMode {
|
||||
@ -154,6 +157,16 @@ impl EditMode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::U, "bulk edit lanes on this road")
|
||||
{
|
||||
state.mode = Mode::Edit(EditMode::BulkEditLanes(
|
||||
state.ui.primary.map.get_l(id).parent,
|
||||
Wizard::new(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(ID::Intersection(id)) = state.ui.primary.current_selection {
|
||||
if state.ui.primary.map.maybe_get_stop_sign(id).is_some()
|
||||
@ -177,6 +190,7 @@ impl EditMode {
|
||||
}
|
||||
}
|
||||
Mode::Edit(EditMode::Saving(ref mut wizard)) => {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if save_edits(wizard.wrap(ctx), &mut state.ui.primary.map).is_some()
|
||||
|| wizard.aborted()
|
||||
{
|
||||
@ -184,6 +198,7 @@ impl EditMode {
|
||||
}
|
||||
}
|
||||
Mode::Edit(EditMode::Loading(ref mut wizard)) => {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if let Some(new_edits) = load_edits(
|
||||
&state.ui.primary.map,
|
||||
&mut wizard.wrap(ctx),
|
||||
@ -205,6 +220,15 @@ impl EditMode {
|
||||
state.mode = Mode::Edit(EditMode::new(ctx, &mut state.ui));
|
||||
}
|
||||
}
|
||||
Mode::Edit(EditMode::BulkEditLanes(r, ref mut wizard)) => {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if let Some(edits) = bulk_edit(r, &mut wizard.wrap(ctx), &state.ui.primary.map) {
|
||||
apply_map_edits(&mut state.ui, ctx, edits);
|
||||
state.mode = Mode::Edit(EditMode::new(ctx, &mut state.ui));
|
||||
} else if wizard.aborted() {
|
||||
state.mode = Mode::Edit(EditMode::new(ctx, &mut state.ui));
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
@ -288,7 +312,8 @@ impl EditMode {
|
||||
menu.draw(g);
|
||||
}
|
||||
Mode::Edit(EditMode::Saving(ref wizard))
|
||||
| Mode::Edit(EditMode::Loading(ref wizard)) => {
|
||||
| Mode::Edit(EditMode::Loading(ref wizard))
|
||||
| Mode::Edit(EditMode::BulkEditLanes(_, ref wizard)) => {
|
||||
state.ui.draw(
|
||||
g,
|
||||
DrawOptions::new(),
|
||||
@ -488,3 +513,60 @@ fn load_edits(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<MapE
|
||||
)
|
||||
.map(|(_, e)| e)
|
||||
}
|
||||
|
||||
fn bulk_edit(r: RoadID, wizard: &mut WrappedWizard, map: &Map) -> Option<MapEdits> {
|
||||
let from = wizard
|
||||
.choose_something(
|
||||
"Change all lanes of type...",
|
||||
Box::new(|| {
|
||||
vec![
|
||||
(None, "driving".to_string(), LaneType::Driving),
|
||||
(None, "parking".to_string(), LaneType::Parking),
|
||||
(None, "biking".to_string(), LaneType::Biking),
|
||||
(None, "bus".to_string(), LaneType::Bus),
|
||||
]
|
||||
}),
|
||||
)?
|
||||
.1;
|
||||
let to = wizard
|
||||
.choose_something(
|
||||
"Change to all lanes of type...",
|
||||
Box::new(move || {
|
||||
vec![
|
||||
(None, "driving".to_string(), LaneType::Driving),
|
||||
(None, "parking".to_string(), LaneType::Parking),
|
||||
(None, "biking".to_string(), LaneType::Biking),
|
||||
(None, "bus".to_string(), LaneType::Bus),
|
||||
]
|
||||
.into_iter()
|
||||
.filter(|(_, _, lt)| *lt != from)
|
||||
.collect()
|
||||
}),
|
||||
)?
|
||||
.1;
|
||||
|
||||
// Do the dirty deed. Match by road name; OSM way ID changes a fair bit.
|
||||
let road_name = map.get_r(r).get_name();
|
||||
let mut edits = map.get_edits().clone();
|
||||
let mut cnt = 0;
|
||||
for l in map.all_lanes() {
|
||||
if l.lane_type != from {
|
||||
continue;
|
||||
}
|
||||
let parent = map.get_parent(l.id);
|
||||
if parent.get_name() != road_name {
|
||||
continue;
|
||||
}
|
||||
// TODO This looks at the original state of the map, not with all the edits applied so far!
|
||||
if can_change_lane_type(parent, l, to, map) {
|
||||
edits.lane_overrides.insert(l.id, to);
|
||||
cnt += 1;
|
||||
}
|
||||
}
|
||||
// TODO pop this up. warn about road names changing and being weird. :)
|
||||
println!(
|
||||
"Changed {} {:?} lanes to {:?} lanes on {}",
|
||||
cnt, from, to, road_name
|
||||
);
|
||||
Some(edits)
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ pub const LANE_THICKNESS: Distance = Distance::const_meters(2.5);
|
||||
|
||||
impl Cloneable for ControlTrafficSignal {}
|
||||
impl Cloneable for IntersectionID {}
|
||||
impl Cloneable for LaneType {}
|
||||
impl Cloneable for MapEdits {}
|
||||
impl Cloneable for Neighborhood {}
|
||||
impl Cloneable for NeighborhoodBuilder {}
|
||||
|
Loading…
Reference in New Issue
Block a user