game/devtools/
scenario.rs1use abstutil::prettyprint_usize;
2use map_gui::tools::ColorDiscrete;
3use sim::count_parked_cars_per_bldg;
4use synthpop::Scenario;
5use widgetry::mapspace::ToggleZoomed;
6use widgetry::{
7 Color, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, State, Text,
8 VerticalAlignment, Widget,
9};
10
11use crate::app::{App, Transition};
12use crate::common::CommonState;
13use crate::devtools::destinations::PopularDestinations;
14
15pub struct ScenarioManager {
16 panel: Panel,
17 scenario: Scenario,
18 draw: ToggleZoomed,
19}
20
21impl ScenarioManager {
22 pub fn new_state(scenario: Scenario, ctx: &mut EventCtx, app: &App) -> Box<dyn State<App>> {
23 let mut colorer = ColorDiscrete::new(
24 app,
25 vec![
26 ("1-2", Color::BLUE),
27 ("3-4", Color::RED),
28 ("more", Color::BLACK),
29 ],
30 );
31 let mut total_cars_needed = 0;
32 for (b, count) in count_parked_cars_per_bldg(&scenario).consume() {
33 total_cars_needed += count;
34 let color = if count == 0 {
35 continue;
36 } else if count == 1 || count == 2 {
37 "1-2"
38 } else if count == 3 || count == 4 {
39 "3-4"
40 } else {
41 "more"
42 };
43 colorer.add_b(b, color);
44 }
45
46 let (filled_spots, free_parking_spots) = app.primary.sim.get_all_parking_spots();
47 assert!(filled_spots.is_empty());
48
49 let (draw, legend) = colorer.build(ctx);
50 Box::new(ScenarioManager {
51 panel: Panel::new_builder(Widget::col(vec![
52 Widget::row(vec![
53 Line(format!("Scenario {}", scenario.scenario_name))
54 .small_heading()
55 .into_widget(ctx),
56 ctx.style().btn_close_widget(ctx),
57 ]),
58 ctx.style()
59 .btn_outline
60 .text("popular destinations")
61 .hotkey(Key::D)
62 .build_def(ctx),
63 Text::from_multiline(vec![
64 Line(format!(
65 "{} people",
66 prettyprint_usize(scenario.people.len())
67 )),
68 Line(format!(
69 "seed {} parked cars",
70 prettyprint_usize(total_cars_needed)
71 )),
72 Line(format!(
73 "{} parking spots",
74 prettyprint_usize(free_parking_spots.len()),
75 )),
76 Line(""),
77 Line("Parked cars per building"),
78 ])
79 .into_widget(ctx),
80 legend,
81 ]))
82 .aligned(HorizontalAlignment::Right, VerticalAlignment::Top)
83 .build(ctx),
84 draw,
85 scenario,
86 })
87 }
88}
89
90impl State<App> for ScenarioManager {
91 fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
92 if let Outcome::Clicked(x) = self.panel.event(ctx) {
93 match x.as_ref() {
94 "close" => {
95 return Transition::Pop;
96 }
97 "popular destinations" => {
98 return Transition::Push(PopularDestinations::new_state(
99 ctx,
100 app,
101 &self.scenario,
102 ));
103 }
104 _ => unreachable!(),
105 }
106 }
107
108 ctx.canvas_movement();
109 if ctx.redo_mouseover() {
110 app.recalculate_current_selection(ctx);
111 }
112
113 Transition::Keep
114 }
115
116 fn draw(&self, g: &mut GfxCtx, app: &App) {
117 self.draw.draw(g);
118 self.panel.draw(g);
119 CommonState::draw_osd(g, app);
120 }
121}