mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-28 08:53:26 +03:00
Record timing while applying map edits. Even in release mode, this is a long inexplicable pause for large-scale bike network changes. A loading screen is better.
This commit is contained in:
parent
0fc1af0dd9
commit
309db511c2
@ -499,7 +499,9 @@ impl State<App> for SaveEdits {
|
||||
"Save" => {
|
||||
let mut edits = app.primary.map.get_edits().clone();
|
||||
edits.edits_name = self.current_name.clone();
|
||||
app.primary.map.must_apply_edits(edits);
|
||||
app.primary
|
||||
.map
|
||||
.must_apply_edits(edits, &mut Timer::throwaway());
|
||||
app.primary.map.save_edits();
|
||||
if self.reset {
|
||||
apply_map_edits(ctx, app, app.primary.map.new_edits());
|
||||
@ -687,57 +689,57 @@ fn make_topcenter(ctx: &mut EventCtx, app: &App) -> Panel {
|
||||
}
|
||||
|
||||
pub fn apply_map_edits(ctx: &mut EventCtx, app: &mut App, edits: MapEdits) {
|
||||
let mut timer = Timer::new("apply map edits");
|
||||
|
||||
if app.primary.unedited_map.is_none() {
|
||||
timer.start("save unedited map");
|
||||
assert!(app.primary.map.get_edits().commands.is_empty());
|
||||
app.primary.unedited_map = Some(app.primary.map.clone());
|
||||
timer.stop("save unedited map");
|
||||
}
|
||||
|
||||
timer.start("edit map");
|
||||
let effects = app.primary.map.must_apply_edits(edits);
|
||||
timer.stop("edit map");
|
||||
|
||||
if !effects.changed_roads.is_empty() || !effects.changed_intersections.is_empty() {
|
||||
app.primary
|
||||
.draw_map
|
||||
.draw_all_unzoomed_roads_and_intersections =
|
||||
DrawMap::regenerate_unzoomed_layer(&app.primary.map, &app.cs, ctx, &mut timer);
|
||||
}
|
||||
|
||||
for l in effects.deleted_lanes {
|
||||
app.primary.draw_map.delete_lane(l);
|
||||
}
|
||||
|
||||
for r in effects.changed_roads {
|
||||
let road = app.primary.map.get_r(r);
|
||||
app.primary.draw_map.recreate_road(road, &app.primary.map);
|
||||
|
||||
// An edit to one lane potentially affects markings in all lanes in the same road, because
|
||||
// of one-way markings, driving lines, etc.
|
||||
for l in &road.lanes {
|
||||
app.primary.draw_map.create_lane(l.id, &app.primary.map);
|
||||
ctx.loading_screen("apply map edits", |ctx, timer| {
|
||||
if app.primary.unedited_map.is_none() {
|
||||
timer.start("save unedited map");
|
||||
assert!(app.primary.map.get_edits().commands.is_empty());
|
||||
app.primary.unedited_map = Some(app.primary.map.clone());
|
||||
timer.stop("save unedited map");
|
||||
}
|
||||
}
|
||||
|
||||
for i in effects.changed_intersections {
|
||||
app.primary
|
||||
.draw_map
|
||||
.recreate_intersection(i, &app.primary.map);
|
||||
}
|
||||
timer.start("edit map");
|
||||
let effects = app.primary.map.must_apply_edits(edits, timer);
|
||||
timer.stop("edit map");
|
||||
|
||||
for pl in effects.changed_parking_lots {
|
||||
app.primary.draw_map.get_pl(pl).clear_rendering();
|
||||
}
|
||||
if !effects.changed_roads.is_empty() || !effects.changed_intersections.is_empty() {
|
||||
app.primary
|
||||
.draw_map
|
||||
.draw_all_unzoomed_roads_and_intersections =
|
||||
DrawMap::regenerate_unzoomed_layer(&app.primary.map, &app.cs, ctx, timer);
|
||||
}
|
||||
|
||||
if app.primary.layer.as_ref().and_then(|l| l.name()) == Some("map edits") {
|
||||
app.primary.layer = Some(Box::new(crate::layer::map::Static::edits(ctx, app)));
|
||||
}
|
||||
for l in effects.deleted_lanes {
|
||||
app.primary.draw_map.delete_lane(l);
|
||||
}
|
||||
|
||||
// Autosave
|
||||
app.primary.map.save_edits();
|
||||
for r in effects.changed_roads {
|
||||
let road = app.primary.map.get_r(r);
|
||||
app.primary.draw_map.recreate_road(road, &app.primary.map);
|
||||
|
||||
// An edit to one lane potentially affects markings in all lanes in the same road, because
|
||||
// of one-way markings, driving lines, etc.
|
||||
for l in &road.lanes {
|
||||
app.primary.draw_map.create_lane(l.id, &app.primary.map);
|
||||
}
|
||||
}
|
||||
|
||||
for i in effects.changed_intersections {
|
||||
app.primary
|
||||
.draw_map
|
||||
.recreate_intersection(i, &app.primary.map);
|
||||
}
|
||||
|
||||
for pl in effects.changed_parking_lots {
|
||||
app.primary.draw_map.get_pl(pl).clear_rendering();
|
||||
}
|
||||
|
||||
if app.primary.layer.as_ref().and_then(|l| l.name()) == Some("map edits") {
|
||||
app.primary.layer = Some(Box::new(crate::layer::map::Static::edits(ctx, app)));
|
||||
}
|
||||
|
||||
// Autosave
|
||||
app.primary.map.save_edits();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn can_edit_lane(app: &App, l: LaneID) -> bool {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use abstutil::Timer;
|
||||
use map_gui::tools::PopupMsg;
|
||||
use map_model::{connectivity, EditCmd, PathConstraints};
|
||||
use widgetry::{EventCtx, State};
|
||||
@ -21,11 +22,15 @@ pub fn check_sidewalk_connectivity(
|
||||
|
||||
let mut edits = orig_edits.clone();
|
||||
edits.commands.push(cmd);
|
||||
app.primary.map.try_apply_edits(edits);
|
||||
app.primary
|
||||
.map
|
||||
.try_apply_edits(edits, &mut Timer::throwaway());
|
||||
|
||||
let (_, disconnected_after) =
|
||||
connectivity::find_scc(&app.primary.map, PathConstraints::Pedestrian);
|
||||
app.primary.map.must_apply_edits(orig_edits);
|
||||
app.primary
|
||||
.map
|
||||
.must_apply_edits(orig_edits, &mut Timer::throwaway());
|
||||
|
||||
let newly_disconnected = disconnected_after
|
||||
.difference(&disconnected_before)
|
||||
@ -68,7 +73,9 @@ pub fn check_blackholes(
|
||||
|
||||
let mut edits = orig_edits.clone();
|
||||
edits.commands.push(cmd);
|
||||
app.primary.map.try_apply_edits(edits);
|
||||
app.primary
|
||||
.map
|
||||
.try_apply_edits(edits, &mut Timer::throwaway());
|
||||
|
||||
let mut newly_disconnected = BTreeSet::new();
|
||||
for l in connectivity::find_scc(&app.primary.map, PathConstraints::Car).1 {
|
||||
@ -81,7 +88,9 @@ pub fn check_blackholes(
|
||||
newly_disconnected.insert(l);
|
||||
}
|
||||
}
|
||||
app.primary.map.must_apply_edits(orig_edits);
|
||||
app.primary
|
||||
.map
|
||||
.must_apply_edits(orig_edits, &mut Timer::throwaway());
|
||||
|
||||
if newly_disconnected.is_empty() {
|
||||
return None;
|
||||
|
@ -202,7 +202,7 @@ fn handle_command(
|
||||
old: map.get_i_edit(id),
|
||||
new: EditIntersection::TrafficSignal(ts.export(map)),
|
||||
});
|
||||
map.must_apply_edits(edits);
|
||||
map.must_apply_edits(edits, &mut Timer::throwaway());
|
||||
map.recalculate_pathfinding_after_edits(&mut Timer::throwaway());
|
||||
|
||||
Ok(format!("{} has been updated", id))
|
||||
@ -476,7 +476,7 @@ impl LoadSim {
|
||||
let mut map = Map::load_synchronously(scenario.map_name.path(), timer);
|
||||
if let Some(perma) = self.edits.clone() {
|
||||
let edits = perma.into_edits(&map).unwrap();
|
||||
map.must_apply_edits(edits);
|
||||
map.must_apply_edits(edits, timer);
|
||||
map.recalculate_pathfinding_after_edits(timer);
|
||||
}
|
||||
|
||||
|
@ -815,17 +815,22 @@ impl Map {
|
||||
}
|
||||
|
||||
/// Returns (changed_roads, deleted_lanes, deleted_turns, added_turns, changed_intersections)
|
||||
pub fn must_apply_edits(&mut self, new_edits: MapEdits) -> EditEffects {
|
||||
self.apply_edits(new_edits, true)
|
||||
pub fn must_apply_edits(&mut self, new_edits: MapEdits, timer: &mut Timer) -> EditEffects {
|
||||
self.apply_edits(new_edits, true, timer)
|
||||
}
|
||||
|
||||
pub fn try_apply_edits(&mut self, new_edits: MapEdits) {
|
||||
self.apply_edits(new_edits, false);
|
||||
pub fn try_apply_edits(&mut self, new_edits: MapEdits, timer: &mut Timer) {
|
||||
self.apply_edits(new_edits, false, timer);
|
||||
}
|
||||
|
||||
// new_edits don't necessarily have to be valid; this could be used for speculatively testing
|
||||
// edits. Doesn't update pathfinding yet.
|
||||
fn apply_edits(&mut self, mut new_edits: MapEdits, enforce_valid: bool) -> EditEffects {
|
||||
fn apply_edits(
|
||||
&mut self,
|
||||
mut new_edits: MapEdits,
|
||||
enforce_valid: bool,
|
||||
timer: &mut Timer,
|
||||
) -> EditEffects {
|
||||
self.edits_generation += 1;
|
||||
|
||||
let mut effects = EditEffects {
|
||||
@ -855,8 +860,9 @@ impl Map {
|
||||
}
|
||||
}
|
||||
|
||||
// Undo existing edits
|
||||
timer.start_iter("undo old edits", self.edits.commands.len() - start_at_idx);
|
||||
for _ in start_at_idx..self.edits.commands.len() {
|
||||
timer.next();
|
||||
self.edits
|
||||
.commands
|
||||
.pop()
|
||||
@ -865,8 +871,9 @@ impl Map {
|
||||
.apply(&mut effects, self);
|
||||
}
|
||||
|
||||
// Apply new edits.
|
||||
timer.start_iter("apply new edits", new_edits.commands.len() - start_at_idx);
|
||||
for cmd in &new_edits.commands[start_at_idx..] {
|
||||
timer.next();
|
||||
cmd.apply(&mut effects, self);
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ impl SimFlags {
|
||||
timer,
|
||||
) {
|
||||
Ok(edits) => {
|
||||
map.must_apply_edits(edits);
|
||||
map.must_apply_edits(edits, timer);
|
||||
map.recalculate_pathfinding_after_edits(timer);
|
||||
}
|
||||
Err(err) => {
|
||||
|
@ -26,7 +26,7 @@ fn main() {
|
||||
{
|
||||
let mut edits = map.get_edits().clone();
|
||||
edits.edits_name = "traffic_seitan".to_string();
|
||||
map.must_apply_edits(edits);
|
||||
map.must_apply_edits(edits, &mut timer);
|
||||
map.recalculate_pathfinding_after_edits(&mut timer);
|
||||
sim.handle_live_edits(&map, &mut timer);
|
||||
}
|
||||
@ -36,7 +36,7 @@ fn main() {
|
||||
})) {
|
||||
let mut edits = map.get_edits().clone();
|
||||
edits.edits_name = "traffic_seitan_crash".to_string();
|
||||
map.must_apply_edits(edits);
|
||||
map.must_apply_edits(edits, &mut timer);
|
||||
map.save_edits();
|
||||
|
||||
println!("Crashed at {}", sim.time());
|
||||
@ -58,7 +58,7 @@ fn run(map: &mut Map, sim: &mut Sim, rng: &mut XorShiftRng, timer: &mut Timer) {
|
||||
nuke_random_parking(map, rng, &mut edits);
|
||||
alter_turn_destinations(sim, map, rng, &mut edits);
|
||||
|
||||
map.must_apply_edits(edits);
|
||||
map.must_apply_edits(edits, timer);
|
||||
map.recalculate_pathfinding_after_edits(timer);
|
||||
sim.handle_live_edited_traffic_signals(map);
|
||||
sim.handle_live_edits(map, timer);
|
||||
|
Loading…
Reference in New Issue
Block a user