prevent creating new parking blackholes before confirming edits. the

check is too conservative right now.
This commit is contained in:
Dustin Carlino 2020-05-04 15:04:39 -07:00
parent 0f39ea46ce
commit 4ffabadaf2
4 changed files with 53 additions and 7 deletions

View File

@ -1,6 +1,6 @@
use crate::app::App; use crate::app::App;
use crate::common::CommonState; use crate::common::CommonState;
use crate::edit::{apply_map_edits, can_edit_lane}; use crate::edit::{apply_map_edits, can_edit_lane, check_parking_blackholes};
use crate::game::{msg, State, Transition, WizardState}; use crate::game::{msg, State, Transition, WizardState};
use crate::helpers::ID; use crate::helpers::ID;
use crate::render::Renderable; use crate::render::Renderable;
@ -170,7 +170,12 @@ impl State for LaneEditor {
Ok(cmd) => { Ok(cmd) => {
let mut edits = app.primary.map.get_edits().clone(); let mut edits = app.primary.map.get_edits().clone();
edits.commands.push(cmd); edits.commands.push(cmd);
apply_map_edits(ctx, app, edits);
// Not so fast!
if let Some(err_state) = check_parking_blackholes(ctx, app, edits) {
return Transition::Push(err_state);
}
return Transition::Replace(Box::new(LaneEditor::new( return Transition::Replace(Box::new(LaneEditor::new(
ctx, ctx,
app, app,

View File

@ -495,3 +495,42 @@ pub fn close_intersection(
Transition::Replace(err_state) Transition::Replace(err_state)
} }
} }
pub fn check_parking_blackholes(
ctx: &mut EventCtx,
app: &mut App,
edits: MapEdits,
) -> Option<Box<dyn State>> {
let orig_edits = app.primary.map.get_edits().clone();
let mut ok_originally = BTreeSet::new();
for l in app.primary.map.all_lanes() {
if l.parking_blackhole.is_none() {
ok_originally.insert(l.id);
// TODO Only matters if there's any parking here anyways
}
}
apply_map_edits(ctx, app, edits);
let color = Color::RED;
let mut num_problems = 0;
let mut c = Colorer::discrete(ctx, "", Vec::new(), vec![("parking disconnected", color)]);
for (l, _) in
connectivity::redirect_parking_blackholes(&app.primary.map, &mut Timer::throwaway())
{
if ok_originally.contains(&l) {
num_problems += 1;
c.add_l(l, color, &app.primary.map);
}
}
if num_problems == 0 {
None
} else {
apply_map_edits(ctx, app, orig_edits);
let mut err_state = msg(
"Error",
vec![format!("{} lanes have parking disconnected", num_problems)],
);
err_state.downcast_mut::<WizardState>().unwrap().also_draw = Some(c.build_zoomed(ctx, app));
Some(err_state)
}
}

View File

@ -270,6 +270,10 @@ impl WizardState {
impl State for WizardState { impl State for WizardState {
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition { fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
if self.also_draw.is_some() {
// TODO This should really be a separate option
ctx.canvas_movement();
}
if let Some(t) = (self.cb)(&mut self.wizard, ctx, app) { if let Some(t) = (self.cb)(&mut self.wizard, ctx, app) {
return t; return t;
} else if self.wizard.aborted() { } else if self.wizard.aborted() {
@ -283,14 +287,12 @@ impl State for WizardState {
} }
fn draw(&self, g: &mut GfxCtx, app: &App) { fn draw(&self, g: &mut GfxCtx, app: &App) {
// TODO This shouldn't get greyed out, but I think the weird z-ordering of screen-space
// right now is messing this up.
if let Some(ref d) = self.also_draw { if let Some(ref d) = self.also_draw {
g.redraw(d); g.redraw(d);
} else {
State::grey_out_map(g, app);
} }
State::grey_out_map(g, app);
self.wizard.draw(g); self.wizard.draw(g);
} }
} }

View File

@ -43,7 +43,7 @@ pub fn find_scc(map: &Map, constraints: PathConstraints) -> (HashSet<LaneID>, Ha
// //
// It's a bit weird to never attempt parking on roads not part of the largest SCC of the graph. // It's a bit weird to never attempt parking on roads not part of the largest SCC of the graph.
// This is acceptable, because there shouldn't be too many roads outside of that SCC anyway. // This is acceptable, because there shouldn't be too many roads outside of that SCC anyway.
pub(crate) fn redirect_parking_blackholes(map: &Map, timer: &mut Timer) -> Vec<(LaneID, LaneID)> { pub fn redirect_parking_blackholes(map: &Map, timer: &mut Timer) -> Vec<(LaneID, LaneID)> {
let (largest_group, disconnected) = find_scc(map, PathConstraints::Car); let (largest_group, disconnected) = find_scc(map, PathConstraints::Car);
let mut redirects = Vec::new(); let mut redirects = Vec::new();