mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-01 10:44:56 +03:00
use WizardState for some more things, making proper use of bundling state with closures!
This commit is contained in:
parent
02e850f3d7
commit
38ea097b26
@ -82,10 +82,7 @@ impl State for ABTestSetup {
|
||||
} else if self.menu.action("run A/B test") {
|
||||
return Transition::Replace(Box::new(launch_test(&self.ab_test, ui, ctx)));
|
||||
} else if self.menu.action("load savestate") {
|
||||
return Transition::Push(Box::new(LoadSavestate {
|
||||
ab_test: self.ab_test.clone(),
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(make_load_savestate(self.ab_test.clone()));
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
@ -96,24 +93,19 @@ impl State for ABTestSetup {
|
||||
}
|
||||
}
|
||||
|
||||
struct LoadSavestate {
|
||||
ab_test: ABTest,
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for LoadSavestate {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
if let Some(ss) = pick_savestate(&self.ab_test, &mut self.wizard.wrap(ctx)) {
|
||||
return Transition::Replace(Box::new(launch_savestate(&self.ab_test, ss, ui, ctx)));
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
fn make_load_savestate(ab_test: ABTest) -> Box<State> {
|
||||
WizardState::new(Box::new(move |wiz, ctx, ui| {
|
||||
let ss = wiz.wrap(ctx).choose_string("Load which savestate?", || {
|
||||
abstutil::list_dir(std::path::Path::new(&abstutil::path1(
|
||||
&ab_test.map_name,
|
||||
abstutil::AB_TEST_SAVES,
|
||||
&ab_test.test_name,
|
||||
)))
|
||||
})?;
|
||||
Some(Transition::Replace(Box::new(launch_savestate(
|
||||
&ab_test, ss, ui, ctx,
|
||||
))))
|
||||
}))
|
||||
}
|
||||
|
||||
fn launch_test(test: &ABTest, ui: &mut UI, ctx: &mut EventCtx) -> ABTestMode {
|
||||
@ -244,10 +236,3 @@ fn choose_edits(map_name: &str, wizard: &mut WrappedWizard, query: &str) -> Opti
|
||||
list
|
||||
})
|
||||
}
|
||||
|
||||
fn pick_savestate(test: &ABTest, wizard: &mut WrappedWizard) -> Option<String> {
|
||||
let path = abstutil::path1(&test.map_name, abstutil::AB_TEST_SAVES, &test.test_name);
|
||||
wizard.choose_string("Load which savestate?", || {
|
||||
abstutil::list_dir(std::path::Path::new(&path))
|
||||
})
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::common::CommonState;
|
||||
use crate::game::{State, Transition};
|
||||
use crate::game::{State, Transition, WizardState};
|
||||
use crate::helpers::ID;
|
||||
use crate::ui::UI;
|
||||
use ezgui::{EventCtx, GfxCtx, Key, ModalMenu, Text, WarpingItemSlider, Wizard};
|
||||
use ezgui::{EventCtx, GfxCtx, Key, ModalMenu, Text, WarpingItemSlider};
|
||||
use geom::Pt2D;
|
||||
use map_model::{BusRoute, BusRouteID, BusStopID, Map};
|
||||
|
||||
@ -32,10 +32,9 @@ impl BusRouteExplorer {
|
||||
ctx,
|
||||
)))
|
||||
} else {
|
||||
Some(Box::new(BusRoutePicker {
|
||||
choices: routes.into_iter().map(|r| r.id).collect(),
|
||||
wizard: Wizard::new(),
|
||||
}))
|
||||
Some(make_bus_route_picker(
|
||||
routes.into_iter().map(|r| r.id).collect(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,54 +82,37 @@ impl State for BusRouteExplorer {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BusRoutePicker {
|
||||
choices: Vec<BusRouteID>,
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
pub struct BusRoutePicker;
|
||||
impl BusRoutePicker {
|
||||
pub fn new(ui: &UI, menu: &mut ModalMenu) -> Option<BusRoutePicker> {
|
||||
pub fn new(ui: &UI, menu: &mut ModalMenu) -> Option<Box<State>> {
|
||||
if !menu.action("explore a bus route") {
|
||||
return None;
|
||||
}
|
||||
Some(BusRoutePicker {
|
||||
choices: ui
|
||||
.primary
|
||||
Some(make_bus_route_picker(
|
||||
ui.primary
|
||||
.map
|
||||
.get_all_bus_routes()
|
||||
.iter()
|
||||
.map(|r| r.id)
|
||||
.collect(),
|
||||
wizard: Wizard::new(),
|
||||
})
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl State for BusRoutePicker {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
let choices = self.choices.clone();
|
||||
if let Some((_, id)) =
|
||||
self.wizard
|
||||
.wrap(ctx)
|
||||
.choose_something("Explore which bus route?", || {
|
||||
choices
|
||||
.into_iter()
|
||||
.map(|id| (ui.primary.map.get_br(id).name.clone(), id))
|
||||
.collect()
|
||||
})
|
||||
{
|
||||
return Transition::Replace(Box::new(BusRouteExplorer::for_route(
|
||||
ui.primary.map.get_br(id),
|
||||
&ui.primary.map,
|
||||
ctx,
|
||||
)));
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
fn make_bus_route_picker(choices: Vec<BusRouteID>) -> Box<State> {
|
||||
WizardState::new(Box::new(move |wiz, ctx, ui| {
|
||||
let (_, id) = wiz
|
||||
.wrap(ctx)
|
||||
.choose_something("Explore which bus route?", || {
|
||||
choices
|
||||
.iter()
|
||||
.map(|id| (ui.primary.map.get_br(*id).name.clone(), *id))
|
||||
.collect()
|
||||
})?;
|
||||
Some(Transition::Replace(Box::new(BusRouteExplorer::for_route(
|
||||
ui.primary.map.get_br(id),
|
||||
&ui.primary.map,
|
||||
ctx,
|
||||
))))
|
||||
}))
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ impl State for DebugMode {
|
||||
return Transition::PushWithMode(explorer, EventLoopMode::Animation);
|
||||
}
|
||||
if let Some(picker) = bus_explorer::BusRoutePicker::new(ui, &mut self.menu) {
|
||||
return Transition::Push(Box::new(picker));
|
||||
return Transition::Push(picker);
|
||||
}
|
||||
|
||||
Transition::Keep
|
||||
|
@ -12,7 +12,7 @@ use crate::render::{
|
||||
use crate::sandbox::SandboxMode;
|
||||
use crate::ui::{PerMapUI, ShowEverything, UI};
|
||||
use abstutil::Timer;
|
||||
use ezgui::{hotkey, lctrl, Color, EventCtx, GfxCtx, Key, ModalMenu, Text, Wizard, WrappedWizard};
|
||||
use ezgui::{hotkey, lctrl, Color, EventCtx, GfxCtx, Key, ModalMenu, Text, Wizard};
|
||||
use map_model::{
|
||||
IntersectionID, Lane, LaneID, LaneType, Map, MapEdits, Road, RoadID, TurnID, TurnType,
|
||||
};
|
||||
@ -150,10 +150,7 @@ impl State for EditMode {
|
||||
.input
|
||||
.contextual_action(Key::U, "bulk edit lanes on this road")
|
||||
{
|
||||
return Transition::Push(Box::new(BulkEditLanes {
|
||||
road: ui.primary.map.get_l(id).parent,
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(make_bulk_edit_lanes(ui.primary.map.get_l(id).parent));
|
||||
} else if orig_edits.lane_overrides.contains_key(&id)
|
||||
&& ctx.input.contextual_action(Key::R, "revert")
|
||||
{
|
||||
@ -474,73 +471,54 @@ pub fn apply_map_edits(
|
||||
bundle.map.simplify_edits(&mut timer);
|
||||
}
|
||||
|
||||
struct BulkEditLanes {
|
||||
road: RoadID,
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for BulkEditLanes {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if let Some(edits) = bulk_edit(self.road, &mut self.wizard.wrap(ctx), &ui.primary.map) {
|
||||
apply_map_edits(&mut ui.primary, &ui.cs, ctx, edits);
|
||||
Transition::Pop
|
||||
} else if self.wizard.aborted() {
|
||||
Transition::Pop
|
||||
} else {
|
||||
Transition::Keep
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
// TODO Still draw the diffs, yo
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
fn bulk_edit(r: RoadID, wizard: &mut WrappedWizard, map: &Map) -> Option<MapEdits> {
|
||||
let (_, from) = wizard.choose_something("Change all lanes of type...", || {
|
||||
vec![
|
||||
("driving".to_string(), LaneType::Driving),
|
||||
("parking".to_string(), LaneType::Parking),
|
||||
("biking".to_string(), LaneType::Biking),
|
||||
("bus".to_string(), LaneType::Bus),
|
||||
]
|
||||
})?;
|
||||
let (_, to) = wizard.choose_something("Change to all lanes of type...", || {
|
||||
vec![
|
||||
("driving".to_string(), LaneType::Driving),
|
||||
("parking".to_string(), LaneType::Parking),
|
||||
("biking".to_string(), LaneType::Biking),
|
||||
("bus".to_string(), LaneType::Bus),
|
||||
]
|
||||
.into_iter()
|
||||
.filter(|(_, lt)| *lt != from)
|
||||
.collect()
|
||||
})?;
|
||||
|
||||
// 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)
|
||||
fn make_bulk_edit_lanes(road: RoadID) -> Box<State> {
|
||||
WizardState::new(Box::new(move |wiz, ctx, ui| {
|
||||
let mut wizard = wiz.wrap(ctx);
|
||||
let (_, from) = wizard.choose_something("Change all lanes of type...", || {
|
||||
vec![
|
||||
("driving".to_string(), LaneType::Driving),
|
||||
("parking".to_string(), LaneType::Parking),
|
||||
("biking".to_string(), LaneType::Biking),
|
||||
("bus".to_string(), LaneType::Bus),
|
||||
]
|
||||
})?;
|
||||
let (_, to) = wizard.choose_something("Change to all lanes of type...", || {
|
||||
vec![
|
||||
("driving".to_string(), LaneType::Driving),
|
||||
("parking".to_string(), LaneType::Parking),
|
||||
("biking".to_string(), LaneType::Biking),
|
||||
("bus".to_string(), LaneType::Bus),
|
||||
]
|
||||
.into_iter()
|
||||
.filter(|(_, lt)| *lt != from)
|
||||
.collect()
|
||||
})?;
|
||||
|
||||
// Do the dirty deed. Match by road name; OSM way ID changes a fair bit.
|
||||
let map = &ui.primary.map;
|
||||
let road_name = map.get_r(road).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
|
||||
);
|
||||
apply_map_edits(&mut ui.primary, &ui.cs, ctx, edits);
|
||||
Some(Transition::Pop)
|
||||
}))
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
use crate::common::CommonState;
|
||||
use crate::edit::apply_map_edits;
|
||||
use crate::game::{State, Transition};
|
||||
use crate::game::{State, Transition, WizardState};
|
||||
use crate::helpers::ID;
|
||||
use crate::render::{draw_signal_cycle, DrawCtx, DrawOptions, DrawTurn, TrafficSignalDiagram};
|
||||
use crate::ui::{ShowEverything, UI};
|
||||
use abstutil::Timer;
|
||||
use ezgui::{hotkey, Color, EventCtx, GeomBatch, GfxCtx, Key, ModalMenu, Wizard, WrappedWizard};
|
||||
use ezgui::{hotkey, Color, EventCtx, GeomBatch, GfxCtx, Key, ModalMenu};
|
||||
use geom::Duration;
|
||||
use map_model::{ControlTrafficSignal, Cycle, IntersectionID, Map, TurnID, TurnPriority, TurnType};
|
||||
use map_model::{ControlTrafficSignal, Cycle, IntersectionID, TurnID, TurnPriority, TurnType};
|
||||
|
||||
// TODO Warn if there are empty cycles or if some turn is completely absent from the signal.
|
||||
pub struct TrafficSignalEditor {
|
||||
@ -122,15 +122,11 @@ impl State for TrafficSignalEditor {
|
||||
}
|
||||
|
||||
if self.menu.action("change cycle duration") {
|
||||
return Transition::Push(Box::new(ChangeCycleDuration {
|
||||
cycle: signal.cycles[self.diagram.current_cycle()].clone(),
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(make_change_cycle_duration(
|
||||
signal.cycles[self.diagram.current_cycle()].duration,
|
||||
));
|
||||
} else if self.menu.action("choose a preset signal") {
|
||||
return Transition::Push(Box::new(ChangePreset {
|
||||
i: self.diagram.i,
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(make_change_preset(self.diagram.i));
|
||||
} else if self.menu.action("reset to original") {
|
||||
signal = ControlTrafficSignal::get_possible_policies(&ui.primary.map, self.diagram.i)
|
||||
.remove(0)
|
||||
@ -198,7 +194,7 @@ impl State for TrafficSignalEditor {
|
||||
.menu
|
||||
.action("convert to dedicated pedestrian scramble cycle")
|
||||
{
|
||||
convert_to_ped_scramble(&mut signal, self.diagram.i, &ui.primary.map);
|
||||
signal.convert_to_ped_scramble(&ui.primary.map);
|
||||
change_traffic_signal(signal, self.diagram.i, ui, ctx);
|
||||
self.diagram = TrafficSignalDiagram::new(self.diagram.i, 0, &ui.primary.map, ctx);
|
||||
}
|
||||
@ -261,51 +257,6 @@ impl State for TrafficSignalEditor {
|
||||
}
|
||||
}
|
||||
|
||||
fn choose_preset(
|
||||
map: &Map,
|
||||
id: IntersectionID,
|
||||
mut wizard: WrappedWizard,
|
||||
) -> Option<ControlTrafficSignal> {
|
||||
wizard
|
||||
.choose_something("Use which preset for this intersection?", || {
|
||||
ControlTrafficSignal::get_possible_policies(map, id)
|
||||
})
|
||||
.map(|(_, ts)| ts)
|
||||
}
|
||||
|
||||
fn convert_to_ped_scramble(signal: &mut ControlTrafficSignal, i: IntersectionID, map: &Map) {
|
||||
// Remove Crosswalk turns from existing cycles.
|
||||
for cycle in signal.cycles.iter_mut() {
|
||||
// Crosswalks are usually only priority_turns, but also clear out from yield_turns.
|
||||
for t in map.get_turns_in_intersection(i) {
|
||||
if t.turn_type == TurnType::Crosswalk {
|
||||
cycle.priority_turns.remove(&t.id);
|
||||
cycle.yield_turns.remove(&t.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Blindly try to promote yield turns to protected, now that crosswalks are gone.
|
||||
let mut promoted = Vec::new();
|
||||
for t in &cycle.yield_turns {
|
||||
if cycle.could_be_priority_turn(*t, map) {
|
||||
cycle.priority_turns.insert(*t);
|
||||
promoted.push(*t);
|
||||
}
|
||||
}
|
||||
for t in promoted {
|
||||
cycle.yield_turns.remove(&t);
|
||||
}
|
||||
}
|
||||
|
||||
let mut cycle = Cycle::new(i);
|
||||
for t in map.get_turns_in_intersection(i) {
|
||||
if t.between_sidewalks() {
|
||||
cycle.edit_turn(t, TurnPriority::Priority);
|
||||
}
|
||||
}
|
||||
signal.cycles.push(cycle);
|
||||
}
|
||||
|
||||
fn change_traffic_signal(
|
||||
signal: ControlTrafficSignal,
|
||||
i: IntersectionID,
|
||||
@ -322,58 +273,34 @@ fn change_traffic_signal(
|
||||
apply_map_edits(&mut ui.primary, &ui.cs, ctx, new_edits);
|
||||
}
|
||||
|
||||
struct ChangeCycleDuration {
|
||||
cycle: Cycle,
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for ChangeCycleDuration {
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut UI) -> Transition {
|
||||
if let Some(new_duration) = self.wizard.wrap(ctx).input_usize_prefilled(
|
||||
fn make_change_cycle_duration(current_duration: Duration) -> Box<State> {
|
||||
WizardState::new(Box::new(move |wiz, ctx, _| {
|
||||
let new_duration = wiz.wrap(ctx).input_usize_prefilled(
|
||||
"How long should this cycle be?",
|
||||
format!("{}", self.cycle.duration.inner_seconds() as usize),
|
||||
) {
|
||||
return Transition::PopWithData(Box::new(move |state, ui, ctx| {
|
||||
let editor = state.downcast_ref::<TrafficSignalEditor>().unwrap();
|
||||
let mut signal = ui.primary.map.get_traffic_signal(editor.diagram.i).clone();
|
||||
signal.cycles[editor.diagram.current_cycle()].duration =
|
||||
Duration::seconds(new_duration as f64);
|
||||
change_traffic_signal(signal, editor.diagram.i, ui, ctx);
|
||||
}));
|
||||
}
|
||||
if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
format!("{}", current_duration.inner_seconds() as usize),
|
||||
)?;
|
||||
Some(Transition::PopWithData(Box::new(move |state, ui, ctx| {
|
||||
let mut editor = state.downcast_mut::<TrafficSignalEditor>().unwrap();
|
||||
let mut signal = ui.primary.map.get_traffic_signal(editor.diagram.i).clone();
|
||||
let idx = editor.diagram.current_cycle();
|
||||
signal.cycles[idx].duration = Duration::seconds(new_duration as f64);
|
||||
change_traffic_signal(signal, editor.diagram.i, ui, ctx);
|
||||
editor.diagram = TrafficSignalDiagram::new(editor.diagram.i, idx, &ui.primary.map, ctx);
|
||||
})))
|
||||
}))
|
||||
}
|
||||
|
||||
struct ChangePreset {
|
||||
i: IntersectionID,
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for ChangePreset {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
if let Some(new_signal) = choose_preset(&ui.primary.map, self.i, self.wizard.wrap(ctx)) {
|
||||
return Transition::PopWithData(Box::new(move |state, ui, ctx| {
|
||||
let mut editor = state.downcast_mut::<TrafficSignalEditor>().unwrap();
|
||||
editor.diagram =
|
||||
TrafficSignalDiagram::new(editor.diagram.i, 0, &ui.primary.map, ctx);
|
||||
change_traffic_signal(new_signal, editor.diagram.i, ui, ctx);
|
||||
}));
|
||||
}
|
||||
if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
fn make_change_preset(i: IntersectionID) -> Box<State> {
|
||||
WizardState::new(Box::new(move |wiz, ctx, ui| {
|
||||
let (_, new_signal) = wiz
|
||||
.wrap(ctx)
|
||||
.choose_something("Use which preset for this intersection?", || {
|
||||
ControlTrafficSignal::get_possible_policies(&ui.primary.map, i)
|
||||
})?;
|
||||
Some(Transition::PopWithData(Box::new(move |state, ui, ctx| {
|
||||
let mut editor = state.downcast_mut::<TrafficSignalEditor>().unwrap();
|
||||
change_traffic_signal(new_signal, editor.diagram.i, ui, ctx);
|
||||
editor.diagram = TrafficSignalDiagram::new(editor.diagram.i, 0, &ui.primary.map, ctx);
|
||||
})))
|
||||
}))
|
||||
}
|
||||
|
@ -196,8 +196,6 @@ pub enum Transition {
|
||||
ReplaceWithMode(Box<State>, EventLoopMode),
|
||||
}
|
||||
|
||||
// TODO Maybe let callers stash expensive data computed once here, and let the cb borrow it.
|
||||
// Use cases: both BrowseTrips's
|
||||
pub struct WizardState {
|
||||
wizard: Wizard,
|
||||
// Returning None means stay in this WizardState
|
||||
|
@ -375,6 +375,39 @@ impl ControlTrafficSignal {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_to_ped_scramble(&mut self, map: &Map) {
|
||||
// Remove Crosswalk turns from existing cycles.
|
||||
for cycle in self.cycles.iter_mut() {
|
||||
// Crosswalks are usually only priority_turns, but also clear out from yield_turns.
|
||||
for t in map.get_turns_in_intersection(self.id) {
|
||||
if t.turn_type == TurnType::Crosswalk {
|
||||
cycle.priority_turns.remove(&t.id);
|
||||
cycle.yield_turns.remove(&t.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Blindly try to promote yield turns to protected, now that crosswalks are gone.
|
||||
let mut promoted = Vec::new();
|
||||
for t in &cycle.yield_turns {
|
||||
if cycle.could_be_priority_turn(*t, map) {
|
||||
cycle.priority_turns.insert(*t);
|
||||
promoted.push(*t);
|
||||
}
|
||||
}
|
||||
for t in promoted {
|
||||
cycle.yield_turns.remove(&t);
|
||||
}
|
||||
}
|
||||
|
||||
let mut cycle = Cycle::new(self.id);
|
||||
for t in map.get_turns_in_intersection(self.id) {
|
||||
if t.between_sidewalks() {
|
||||
cycle.edit_turn(t, TurnPriority::Priority);
|
||||
}
|
||||
}
|
||||
self.cycles.push(cycle);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
|
Loading…
Reference in New Issue
Block a user