mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-29 12:43:38 +03:00
add in traffic signal offset end-to-end
This commit is contained in:
parent
f39bb7c6cb
commit
318b467f69
@ -4,7 +4,7 @@ use crate::game::{msg, State, Transition, WizardState};
|
|||||||
use crate::helpers::ID;
|
use crate::helpers::ID;
|
||||||
use crate::render::{draw_signal_phase, DrawOptions, DrawTurn, TrafficSignalDiagram};
|
use crate::render::{draw_signal_phase, DrawOptions, DrawTurn, TrafficSignalDiagram};
|
||||||
use crate::ui::{ShowEverything, UI};
|
use crate::ui::{ShowEverything, UI};
|
||||||
use ezgui::{hotkey, Choice, Color, EventCtx, GeomBatch, GfxCtx, Key, ModalMenu};
|
use ezgui::{hotkey, Choice, Color, EventCtx, GeomBatch, GfxCtx, Key, Line, ModalMenu, Text};
|
||||||
use geom::Duration;
|
use geom::Duration;
|
||||||
use map_model::{
|
use map_model::{
|
||||||
ControlTrafficSignal, EditCmd, IntersectionID, Phase, TurnID, TurnPriority, TurnType,
|
ControlTrafficSignal, EditCmd, IntersectionID, Phase, TurnID, TurnPriority, TurnType,
|
||||||
@ -38,6 +38,7 @@ impl TrafficSignalEditor {
|
|||||||
hotkey(Key::B),
|
hotkey(Key::B),
|
||||||
"convert to dedicated pedestrian scramble phase",
|
"convert to dedicated pedestrian scramble phase",
|
||||||
),
|
),
|
||||||
|
(hotkey(Key::O), "change signal offset"),
|
||||||
(hotkey(Key::Escape), "quit"),
|
(hotkey(Key::Escape), "quit"),
|
||||||
],
|
],
|
||||||
ctx,
|
ctx,
|
||||||
@ -52,7 +53,17 @@ impl TrafficSignalEditor {
|
|||||||
|
|
||||||
impl State for TrafficSignalEditor {
|
impl State for TrafficSignalEditor {
|
||||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||||
|
let mut signal = ui.primary.map.get_traffic_signal(self.diagram.i).clone();
|
||||||
|
|
||||||
self.menu.event(ctx);
|
self.menu.event(ctx);
|
||||||
|
// TODO This really needs to be shown in the diagram!
|
||||||
|
self.menu.set_info(
|
||||||
|
ctx,
|
||||||
|
Text::from(Line(format!(
|
||||||
|
"Signal offset: {}",
|
||||||
|
signal.offset.minimal_tostring()
|
||||||
|
))),
|
||||||
|
);
|
||||||
ctx.canvas.handle_event(ctx.input);
|
ctx.canvas.handle_event(ctx.input);
|
||||||
self.diagram.event(ctx, &mut self.menu);
|
self.diagram.event(ctx, &mut self.menu);
|
||||||
|
|
||||||
@ -72,8 +83,6 @@ impl State for TrafficSignalEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut signal = ui.primary.map.get_traffic_signal(self.diagram.i).clone();
|
|
||||||
|
|
||||||
if let Some(id) = self.icon_selected {
|
if let Some(id) = self.icon_selected {
|
||||||
let phase = &mut signal.phases[self.diagram.current_phase()];
|
let phase = &mut signal.phases[self.diagram.current_phase()];
|
||||||
// Just one key to toggle between the 3 states
|
// Just one key to toggle between the 3 states
|
||||||
@ -115,11 +124,13 @@ impl State for TrafficSignalEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.menu.action("change phase duration") {
|
if self.menu.action("change phase duration") {
|
||||||
return Transition::Push(make_change_phase_duration(
|
return Transition::Push(change_phase_duration(
|
||||||
signal.phases[self.diagram.current_phase()].duration,
|
signal.phases[self.diagram.current_phase()].duration,
|
||||||
));
|
));
|
||||||
|
} else if self.menu.action("change signal offset") {
|
||||||
|
return Transition::Push(change_offset(signal.offset));
|
||||||
} else if self.menu.action("choose a preset signal") {
|
} else if self.menu.action("choose a preset signal") {
|
||||||
return Transition::Push(make_change_preset(self.diagram.i));
|
return Transition::Push(change_preset(self.diagram.i));
|
||||||
} else if self.menu.action("reset to original") {
|
} else if self.menu.action("reset to original") {
|
||||||
signal = ControlTrafficSignal::get_possible_policies(&ui.primary.map, self.diagram.i)
|
signal = ControlTrafficSignal::get_possible_policies(&ui.primary.map, self.diagram.i)
|
||||||
.remove(0)
|
.remove(0)
|
||||||
@ -256,7 +267,7 @@ fn change_traffic_signal(signal: ControlTrafficSignal, ui: &mut UI, ctx: &mut Ev
|
|||||||
apply_map_edits(&mut ui.primary, &ui.cs, ctx, edits);
|
apply_map_edits(&mut ui.primary, &ui.cs, ctx, edits);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_change_phase_duration(current_duration: Duration) -> Box<dyn State> {
|
fn change_phase_duration(current_duration: Duration) -> Box<dyn State> {
|
||||||
WizardState::new(Box::new(move |wiz, ctx, _| {
|
WizardState::new(Box::new(move |wiz, ctx, _| {
|
||||||
let new_duration = wiz.wrap(ctx).input_usize_prefilled(
|
let new_duration = wiz.wrap(ctx).input_usize_prefilled(
|
||||||
"How long should this phase be (seconds)?",
|
"How long should this phase be (seconds)?",
|
||||||
@ -273,7 +284,28 @@ fn make_change_phase_duration(current_duration: Duration) -> Box<dyn State> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_change_preset(i: IntersectionID) -> Box<dyn State> {
|
fn change_offset(current_duration: Duration) -> Box<dyn State> {
|
||||||
|
WizardState::new(Box::new(move |wiz, ctx, _| {
|
||||||
|
let new_duration = wiz.wrap(ctx).input_usize_prefilled(
|
||||||
|
"What should the offset of this traffic signal be (seconds)?",
|
||||||
|
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();
|
||||||
|
signal.offset = Duration::seconds(new_duration as f64);
|
||||||
|
change_traffic_signal(signal, ui, ctx);
|
||||||
|
editor.diagram = TrafficSignalDiagram::new(
|
||||||
|
editor.diagram.i,
|
||||||
|
editor.diagram.current_phase(),
|
||||||
|
ui,
|
||||||
|
ctx,
|
||||||
|
);
|
||||||
|
})))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_preset(i: IntersectionID) -> Box<dyn State> {
|
||||||
WizardState::new(Box::new(move |wiz, ctx, ui| {
|
WizardState::new(Box::new(move |wiz, ctx, ui| {
|
||||||
let (_, new_signal) =
|
let (_, new_signal) =
|
||||||
wiz.wrap(ctx)
|
wiz.wrap(ctx)
|
||||||
|
@ -8,6 +8,7 @@ use std::collections::BTreeSet;
|
|||||||
pub struct ControlTrafficSignal {
|
pub struct ControlTrafficSignal {
|
||||||
pub id: IntersectionID,
|
pub id: IntersectionID,
|
||||||
pub phases: Vec<Phase>,
|
pub phases: Vec<Phase>,
|
||||||
|
pub offset: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
@ -66,7 +67,7 @@ impl ControlTrafficSignal {
|
|||||||
cycle_length += p.duration;
|
cycle_length += p.duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut now_offset = now % cycle_length;
|
let mut now_offset = (now + self.offset) % cycle_length;
|
||||||
for (idx, p) in self.phases.iter().enumerate() {
|
for (idx, p) in self.phases.iter().enumerate() {
|
||||||
if now_offset < p.duration {
|
if now_offset < p.duration {
|
||||||
return (idx, p, p.duration - now_offset);
|
return (idx, p, p.duration - now_offset);
|
||||||
@ -160,6 +161,7 @@ impl ControlTrafficSignal {
|
|||||||
let ts = ControlTrafficSignal {
|
let ts = ControlTrafficSignal {
|
||||||
id: intersection,
|
id: intersection,
|
||||||
phases,
|
phases,
|
||||||
|
offset: Duration::ZERO,
|
||||||
};
|
};
|
||||||
// This must succeed
|
// This must succeed
|
||||||
ts.validate(map).unwrap()
|
ts.validate(map).unwrap()
|
||||||
@ -187,7 +189,11 @@ impl ControlTrafficSignal {
|
|||||||
|
|
||||||
let phases = make_phases(map, i, phases);
|
let phases = make_phases(map, i, phases);
|
||||||
|
|
||||||
let ts = ControlTrafficSignal { id: i, phases };
|
let ts = ControlTrafficSignal {
|
||||||
|
id: i,
|
||||||
|
phases,
|
||||||
|
offset: Duration::ZERO,
|
||||||
|
};
|
||||||
ts.validate(map).ok()
|
ts.validate(map).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +242,11 @@ impl ControlTrafficSignal {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
let ts = ControlTrafficSignal { id: i, phases };
|
let ts = ControlTrafficSignal {
|
||||||
|
id: i,
|
||||||
|
phases,
|
||||||
|
offset: Duration::ZERO,
|
||||||
|
};
|
||||||
ts.validate(map).ok()
|
ts.validate(map).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,7 +288,11 @@ impl ControlTrafficSignal {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
let ts = ControlTrafficSignal { id: i, phases };
|
let ts = ControlTrafficSignal {
|
||||||
|
id: i,
|
||||||
|
phases,
|
||||||
|
offset: Duration::ZERO,
|
||||||
|
};
|
||||||
ts.validate(map).ok()
|
ts.validate(map).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +333,11 @@ impl ControlTrafficSignal {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
let ts = ControlTrafficSignal { id: i, phases };
|
let ts = ControlTrafficSignal {
|
||||||
|
id: i,
|
||||||
|
phases,
|
||||||
|
offset: Duration::ZERO,
|
||||||
|
};
|
||||||
ts.validate(map).ok()
|
ts.validate(map).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +389,11 @@ impl ControlTrafficSignal {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
let ts = ControlTrafficSignal { id: i, phases };
|
let ts = ControlTrafficSignal {
|
||||||
|
id: i,
|
||||||
|
phases,
|
||||||
|
offset: Duration::ZERO,
|
||||||
|
};
|
||||||
ts.validate(map).ok()
|
ts.validate(map).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,6 +419,7 @@ impl ControlTrafficSignal {
|
|||||||
let ts = ControlTrafficSignal {
|
let ts = ControlTrafficSignal {
|
||||||
id: i,
|
id: i,
|
||||||
phases: vec![all_walk, all_yield],
|
phases: vec![all_walk, all_yield],
|
||||||
|
offset: Duration::ZERO,
|
||||||
};
|
};
|
||||||
// This must succeed
|
// This must succeed
|
||||||
ts.validate(map).unwrap()
|
ts.validate(map).unwrap()
|
||||||
@ -430,7 +453,11 @@ impl ControlTrafficSignal {
|
|||||||
phases.push(phase);
|
phases.push(phase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let ts = ControlTrafficSignal { id: i, phases };
|
let ts = ControlTrafficSignal {
|
||||||
|
id: i,
|
||||||
|
phases,
|
||||||
|
offset: Duration::ZERO,
|
||||||
|
};
|
||||||
ts.validate(map).ok()
|
ts.validate(map).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user