add in traffic signal offset end-to-end

This commit is contained in:
Dustin Carlino 2019-11-21 10:18:01 -08:00
parent f39bb7c6cb
commit 318b467f69
2 changed files with 73 additions and 14 deletions

View File

@ -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)

View File

@ -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()
} }