game/edit/traffic_signals/
preview.rs1use std::collections::BTreeSet;
2
3use abstutil::Timer;
4use geom::Duration;
5use map_model::IntersectionID;
6use widgetry::tools::ChooseSomething;
7use widgetry::{
8 Choice, EventCtx, GfxCtx, HorizontalAlignment, Key, Outcome, Panel, State, TextExt, UpdateType,
9 VerticalAlignment, Widget,
10};
11
12use crate::app::{App, Transition};
13use crate::sandbox::{spawn_agents_around, TimePanel};
14
15struct PreviewTrafficSignal {
18 panel: Panel,
19 time_panel: TimePanel,
20}
21
22impl PreviewTrafficSignal {
23 fn new_state(ctx: &mut EventCtx, app: &App) -> Box<dyn State<App>> {
24 Box::new(PreviewTrafficSignal {
25 panel: Panel::new_builder(Widget::col(vec![
26 "Previewing traffic signal".text_widget(ctx),
27 ctx.style()
28 .btn_outline
29 .text("back to editing")
30 .hotkey(Key::Escape)
31 .build_def(ctx),
32 ]))
33 .aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
34 .build(ctx),
35 time_panel: TimePanel::new(ctx, app),
36 })
37 }
38}
39
40impl State<App> for PreviewTrafficSignal {
41 fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
42 ctx.canvas_movement();
43
44 if let Outcome::Clicked(x) = self.panel.event(ctx) {
45 match x.as_ref() {
46 "back to editing" => {
47 app.primary.clear_sim();
48 return Transition::Pop;
49 }
50 _ => unreachable!(),
51 }
52 }
53
54 if let Some(t) = self.time_panel.event(ctx, app, None) {
56 return t;
57 }
58 if self.time_panel.is_paused() {
59 Transition::Keep
60 } else {
61 ctx.request_update(UpdateType::Game);
62 Transition::Keep
63 }
64 }
65
66 fn draw(&self, g: &mut GfxCtx, _: &App) {
67 self.panel.draw(g);
68 self.time_panel.draw(g);
69 }
70}
71
72pub fn make_previewer(
74 ctx: &mut EventCtx,
75 app: &App,
76 members: BTreeSet<IntersectionID>,
77 stage: usize,
78) -> Box<dyn State<App>> {
79 let random = "random agents around these intersections".to_string();
80 let right_now = format!(
81 "change the traffic signal live at {}",
82 app.primary.suspended_sim.as_ref().unwrap().time()
83 );
84
85 ChooseSomething::new_state(
86 ctx,
87 "Preview the traffic signal with what kind of traffic?",
88 Choice::strings(vec![random, right_now]),
89 Box::new(move |x, ctx, app| {
90 if x == "random agents around these intersections" {
91 for (idx, i) in members.into_iter().enumerate() {
92 if idx == 0 {
93 let signal = app.primary.map.get_traffic_signal(i);
95 let mut step = Duration::ZERO;
98 for idx in 0..stage {
99 step += signal.stages[idx].stage_type.simple_duration();
100 }
101 app.primary.sim.timed_step(
102 &app.primary.map,
103 step,
104 &mut app.primary.sim_cb,
105 &mut Timer::throwaway(),
106 );
107 }
108
109 spawn_agents_around(i, app);
110 }
111 } else {
112 app.primary.sim = app.primary.suspended_sim.as_ref().unwrap().clone();
113 app.primary
114 .sim
115 .handle_live_edited_traffic_signals(&app.primary.map);
116 }
117 Transition::Replace(PreviewTrafficSignal::new_state(ctx, app))
118 }),
119 )
120}