diff --git a/game/src/sandbox/gameplay/create_gridlock.rs b/game/src/sandbox/gameplay/create_gridlock.rs index 62c34ca5ed..5602d65f5e 100644 --- a/game/src/sandbox/gameplay/create_gridlock.rs +++ b/game/src/sandbox/gameplay/create_gridlock.rs @@ -6,44 +6,40 @@ use crate::sandbox::gameplay::{cmp_count_fewer, manage_acs, GameplayMode, Gamepl use crate::sandbox::overlays::Overlays; use crate::ui::UI; use abstutil::prettyprint_usize; -use ezgui::{hotkey, EventCtx, Key, Line, ModalMenu, Text}; +use ezgui::{hotkey, layout, EventCtx, GfxCtx, Key, Line, ModalMenu, Text}; use geom::Time; use sim::TripMode; pub struct CreateGridlock { time: Time, + menu: ModalMenu, } impl CreateGridlock { - pub fn new(ctx: &mut EventCtx) -> (ModalMenu, Composite, Box) { + pub fn new(ctx: &mut EventCtx) -> (Composite, Box) { ( - ModalMenu::new( - "Cause gridlock", - vec![ - (hotkey(Key::E), "show agent delay"), - (hotkey(Key::H), "help"), - ], - ctx, - ), edit_map_panel(ctx, GameplayMode::CreateGridlock), Box::new(CreateGridlock { time: Time::START_OF_DAY, + menu: ModalMenu::new( + "Cause gridlock", + vec![ + (hotkey(Key::E), "show agent delay"), + (hotkey(Key::H), "help"), + ], + ctx, + ) + .set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)), }), ) } } impl GameplayState for CreateGridlock { - fn event( - &mut self, - ctx: &mut EventCtx, - ui: &mut UI, - _: &mut Overlays, - menu: &mut ModalMenu, - ) -> Option { - menu.event(ctx); + fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI, _: &mut Overlays) -> Option { + self.menu.event(ctx); manage_acs( - menu, + &mut self.menu, ctx, ui, "show agent delay", @@ -53,10 +49,10 @@ impl GameplayState for CreateGridlock { if self.time != ui.primary.sim.time() { self.time = ui.primary.sim.time(); - menu.set_info(ctx, gridlock_panel(ui)); + self.menu.set_info(ctx, gridlock_panel(ui)); } - if menu.action("help") { + if self.menu.action("help") { return Some(Transition::Push(msg("Help", vec![ "You might notice a few places in the map where gridlock forms already.", "You can make things worse!", @@ -65,6 +61,10 @@ impl GameplayState for CreateGridlock { } None } + + fn draw(&self, g: &mut GfxCtx, _: &UI) { + self.menu.draw(g); + } } fn gridlock_panel(ui: &UI) -> Text { diff --git a/game/src/sandbox/gameplay/faster_trips.rs b/game/src/sandbox/gameplay/faster_trips.rs index 4c193abcca..265ebbf12c 100644 --- a/game/src/sandbox/gameplay/faster_trips.rs +++ b/game/src/sandbox/gameplay/faster_trips.rs @@ -5,51 +5,44 @@ use crate::sandbox::gameplay::{cmp_count_more, cmp_duration_shorter, GameplayMod use crate::sandbox::overlays::Overlays; use crate::ui::UI; use abstutil::prettyprint_usize; -use ezgui::{hotkey, EventCtx, Key, Line, ModalMenu, Text}; +use ezgui::{hotkey, layout, EventCtx, GfxCtx, Key, Line, ModalMenu, Text}; use geom::{Statistic, Time}; use sim::TripMode; pub struct FasterTrips { mode: TripMode, time: Time, + menu: ModalMenu, } impl FasterTrips { - pub fn new( - trip_mode: TripMode, - ctx: &mut EventCtx, - ) -> (ModalMenu, Composite, Box) { + pub fn new(trip_mode: TripMode, ctx: &mut EventCtx) -> (Composite, Box) { ( - ModalMenu::new( - format!("Speed up {} trips", trip_mode), - vec![(hotkey(Key::H), "help")], - ctx, - ), edit_map_panel(ctx, GameplayMode::FasterTrips(trip_mode)), Box::new(FasterTrips { mode: trip_mode, time: Time::START_OF_DAY, + menu: ModalMenu::new( + format!("Speed up {} trips", trip_mode), + vec![(hotkey(Key::H), "help")], + ctx, + ) + .set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)), }), ) } } impl GameplayState for FasterTrips { - fn event( - &mut self, - ctx: &mut EventCtx, - ui: &mut UI, - _: &mut Overlays, - menu: &mut ModalMenu, - ) -> Option { - menu.event(ctx); + fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI, _: &mut Overlays) -> Option { + self.menu.event(ctx); if self.time != ui.primary.sim.time() { self.time = ui.primary.sim.time(); - menu.set_info(ctx, faster_trips_panel(self.mode, ui)); + self.menu.set_info(ctx, faster_trips_panel(self.mode, ui)); } - if menu.action("help") { + if self.menu.action("help") { return Some(Transition::Push(msg( "Help", vec!["How can you possibly speed up all trips of some mode?"], @@ -57,6 +50,10 @@ impl GameplayState for FasterTrips { } None } + + fn draw(&self, g: &mut GfxCtx, _: &UI) { + self.menu.draw(g); + } } pub fn faster_trips_panel(mode: TripMode, ui: &UI) -> Text { diff --git a/game/src/sandbox/gameplay/fix_traffic_signals.rs b/game/src/sandbox/gameplay/fix_traffic_signals.rs index 6879daa932..5bb97fc857 100644 --- a/game/src/sandbox/gameplay/fix_traffic_signals.rs +++ b/game/src/sandbox/gameplay/fix_traffic_signals.rs @@ -5,7 +5,7 @@ use crate::sandbox::gameplay::faster_trips::small_faster_trips_panel; use crate::sandbox::gameplay::{manage_overlays, GameplayMode, GameplayState}; use crate::sandbox::overlays::Overlays; use crate::ui::UI; -use ezgui::{hotkey, EventCtx, Key, ModalMenu}; +use ezgui::{hotkey, layout, EventCtx, GfxCtx, Key, ModalMenu}; use geom::{Duration, Statistic, Time}; use map_model::{IntersectionID, Map}; use sim::{BorderSpawnOverTime, OriginDestination, Scenario, TripMode}; @@ -13,28 +13,27 @@ use sim::{BorderSpawnOverTime, OriginDestination, Scenario, TripMode}; pub struct FixTrafficSignals { time: Time, once: bool, + menu: ModalMenu, } impl FixTrafficSignals { - pub fn new( - ctx: &mut EventCtx, - mode: GameplayMode, - ) -> (ModalMenu, Composite, Box) { + pub fn new(ctx: &mut EventCtx, mode: GameplayMode) -> (Composite, Box) { ( - ModalMenu::new( - "Fix traffic signals", - vec![ - (hotkey(Key::F), "find slowest traffic signals"), - (hotkey(Key::D), "hide finished trip distribution"), - (hotkey(Key::H), "help"), - (hotkey(Key::S), "final score"), - ], - ctx, - ), edit_map_panel(ctx, mode), Box::new(FixTrafficSignals { time: Time::START_OF_DAY, once: true, + menu: ModalMenu::new( + "Fix traffic signals", + vec![ + (hotkey(Key::F), "find slowest traffic signals"), + (hotkey(Key::D), "hide finished trip distribution"), + (hotkey(Key::H), "help"), + (hotkey(Key::S), "final score"), + ], + ctx, + ) + .set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)), }), ) } @@ -46,7 +45,6 @@ impl GameplayState for FixTrafficSignals { ctx: &mut EventCtx, ui: &mut UI, overlays: &mut Overlays, - menu: &mut ModalMenu, ) -> Option { // Once is never... if self.once { @@ -54,11 +52,11 @@ impl GameplayState for FixTrafficSignals { self.once = false; } - menu.event(ctx); + self.menu.event(ctx); // Technically this shows stop signs too, but mostly the bottlenecks are signals. if manage_overlays( - menu, + &mut self.menu, ctx, "find slowest traffic signals", "hide slowest traffic signals", @@ -71,7 +69,7 @@ impl GameplayState for FixTrafficSignals { *overlays = Overlays::intersection_delay(ctx, ui); } if manage_overlays( - menu, + &mut self.menu, ctx, "show finished trip distribution", "hide finished trip distribution", @@ -86,10 +84,11 @@ impl GameplayState for FixTrafficSignals { if self.time != ui.primary.sim.time() { self.time = ui.primary.sim.time(); - menu.set_info(ctx, small_faster_trips_panel(TripMode::Drive, ui)); + self.menu + .set_info(ctx, small_faster_trips_panel(TripMode::Drive, ui)); } - if menu.action("help") { + if self.menu.action("help") { return Some(Transition::Push(msg( "Help", vec![ @@ -98,7 +97,7 @@ impl GameplayState for FixTrafficSignals { ]))); } - if menu.action("final score") { + if self.menu.action("final score") { return Some(Transition::Push(msg("Final score", final_score(ui)))); } @@ -109,6 +108,10 @@ impl GameplayState for FixTrafficSignals { None } + + fn draw(&self, g: &mut GfxCtx, _: &UI) { + self.menu.draw(g); + } } fn final_score(ui: &UI) -> Vec { diff --git a/game/src/sandbox/gameplay/freeform.rs b/game/src/sandbox/gameplay/freeform.rs index aee1a187d0..f4af3da038 100644 --- a/game/src/sandbox/gameplay/freeform.rs +++ b/game/src/sandbox/gameplay/freeform.rs @@ -1,5 +1,5 @@ use crate::edit::EditMode; -use crate::game::{msg, State, Transition, WizardState}; +use crate::game::{State, Transition, WizardState}; use crate::helpers::ID; use crate::managed::Composite; use crate::sandbox::gameplay::{change_scenario, spawner, GameplayMode, GameplayState}; @@ -7,8 +7,8 @@ use crate::sandbox::overlays::Overlays; use crate::sandbox::SandboxMode; use crate::ui::UI; use ezgui::{ - hotkey, lctrl, Color, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, ManagedWidget, - ModalMenu, Text, VerticalAlignment, + hotkey, lctrl, Color, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, ManagedWidget, Text, + VerticalAlignment, }; use map_model::IntersectionID; use std::collections::BTreeSet; @@ -20,9 +20,8 @@ pub struct Freeform { } impl Freeform { - pub fn new(ctx: &mut EventCtx, ui: &UI) -> (ModalMenu, Composite, Box) { + pub fn new(ctx: &mut EventCtx, ui: &UI) -> (Composite, Box) { ( - ModalMenu::new("Freeform mode", vec![(hotkey(Key::H), "help")], ctx), freeform_controller(ctx, ui, GameplayMode::Freeform, "empty scenario"), Box::new(Freeform { spawn_pts: BTreeSet::new(), @@ -32,17 +31,7 @@ impl Freeform { } impl GameplayState for Freeform { - fn event( - &mut self, - ctx: &mut EventCtx, - ui: &mut UI, - _: &mut Overlays, - menu: &mut ModalMenu, - ) -> Option { - menu.event(ctx); - if menu.action("help") { - return Some(Transition::Push(msg("Help", vec!["This simulation is empty by default.", "Try right-clicking an intersection and choosing to spawn agents (or just hover over it and press Z).", "You can also spawn agents from buildings or lanes.", "You can also start a full scenario to get realistic traffic."]))); - } + fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI, _: &mut Overlays) -> Option { if let Some(new_state) = spawner::AgentSpawner::new(ctx, ui) { return Some(Transition::Push(new_state)); } diff --git a/game/src/sandbox/gameplay/mod.rs b/game/src/sandbox/gameplay/mod.rs index 4ef16b0358..a983e8822d 100644 --- a/game/src/sandbox/gameplay/mod.rs +++ b/game/src/sandbox/gameplay/mod.rs @@ -13,14 +13,13 @@ use crate::sandbox::overlays::Overlays; use crate::sandbox::SandboxMode; use crate::ui::UI; use abstutil::{prettyprint_usize, Timer}; -use ezgui::{layout, Color, EventCtx, GfxCtx, Line, ModalMenu, TextSpan, Wizard}; +use ezgui::{Color, EventCtx, GfxCtx, Line, ModalMenu, TextSpan, Wizard}; use geom::Duration; use map_model::{EditCmd, Map, MapEdits}; use sim::{Analytics, Scenario, TripMode}; pub struct GameplayRunner { pub mode: GameplayMode, - pub menu: ModalMenu, controller: Composite, state: Box, } @@ -46,9 +45,8 @@ pub trait GameplayState: downcast_rs::Downcast { ctx: &mut EventCtx, ui: &mut UI, overlays: &mut Overlays, - menu: &mut ModalMenu, ) -> Option; - fn draw(&self, _: &mut GfxCtx, _: &UI) {} + fn draw(&self, g: &mut GfxCtx, ui: &UI); } downcast_rs::impl_downcast!(GameplayState); @@ -135,7 +133,7 @@ impl GameplayMode { impl GameplayRunner { pub fn initialize(mode: GameplayMode, ui: &mut UI, ctx: &mut EventCtx) -> GameplayRunner { - let (menu, controller, state) = match mode.clone() { + let (controller, state) = match mode.clone() { GameplayMode::Freeform => freeform::Freeform::new(ctx, ui), GameplayMode::PlayScenario(scenario) => { play_scenario::PlayScenario::new(&scenario, ctx, ui) @@ -179,8 +177,6 @@ impl GameplayRunner { ui.set_prebaked(Some(prebaked)); GameplayRunner { mode, - menu: menu - .set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)), controller, state, } @@ -199,11 +195,10 @@ impl GameplayRunner { Some(Outcome::Clicked(_)) => unreachable!(), None => {} } - self.state.event(ctx, ui, overlays, &mut self.menu) + self.state.event(ctx, ui, overlays) } pub fn draw(&self, g: &mut GfxCtx, ui: &UI) { - self.menu.draw(g); self.controller.draw(g); self.state.draw(g, ui); } diff --git a/game/src/sandbox/gameplay/optimize_bus.rs b/game/src/sandbox/gameplay/optimize_bus.rs index 4864eaa563..1576aaf5fb 100644 --- a/game/src/sandbox/gameplay/optimize_bus.rs +++ b/game/src/sandbox/gameplay/optimize_bus.rs @@ -6,7 +6,7 @@ use crate::sandbox::gameplay::{ use crate::sandbox::overlays::Overlays; use crate::sandbox::SandboxMode; use crate::ui::UI; -use ezgui::{hotkey, Choice, EventCtx, Key, Line, ModalMenu, Text}; +use ezgui::{hotkey, layout, Choice, EventCtx, GfxCtx, Key, Line, ModalMenu, Text}; use geom::{Statistic, Time}; use map_model::BusRouteID; @@ -14,6 +14,7 @@ pub struct OptimizeBus { route: BusRouteID, time: Time, stat: Statistic, + menu: ModalMenu, } impl OptimizeBus { @@ -21,25 +22,26 @@ impl OptimizeBus { route_name: String, ctx: &mut EventCtx, ui: &UI, - ) -> (ModalMenu, crate::managed::Composite, Box) { + ) -> (crate::managed::Composite, Box) { let route = ui.primary.map.get_bus_route(&route_name).unwrap(); ( - ModalMenu::new( - format!("Optimize {}", route_name), - vec![ - (hotkey(Key::E), "show bus route"), - (hotkey(Key::T), "show delays over time"), - (hotkey(Key::P), "show bus passengers"), - (hotkey(Key::S), "change statistic"), - (hotkey(Key::H), "help"), - ], - ctx, - ), edit_map_panel(ctx, GameplayMode::OptimizeBus(route_name.clone())), Box::new(OptimizeBus { route: route.id, time: Time::START_OF_DAY, stat: Statistic::Max, + menu: ModalMenu::new( + format!("Optimize {}", route_name), + vec![ + (hotkey(Key::E), "show bus route"), + (hotkey(Key::T), "show delays over time"), + (hotkey(Key::P), "show bus passengers"), + (hotkey(Key::S), "change statistic"), + (hotkey(Key::H), "help"), + ], + ctx, + ) + .set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)), }), ) } @@ -51,11 +53,10 @@ impl GameplayState for OptimizeBus { ctx: &mut EventCtx, ui: &mut UI, overlays: &mut Overlays, - menu: &mut ModalMenu, ) -> Option { - menu.event(ctx); + self.menu.event(ctx); if manage_overlays( - menu, + &mut self.menu, ctx, "show bus route", "hide bus route", @@ -68,7 +69,7 @@ impl GameplayState for OptimizeBus { *overlays = Overlays::show_bus_route(self.route, ctx, ui); } if manage_overlays( - menu, + &mut self.menu, ctx, "show delays over time", "hide delays over time", @@ -81,7 +82,7 @@ impl GameplayState for OptimizeBus { *overlays = Overlays::delays_over_time(self.route, ctx, ui); } if manage_overlays( - menu, + &mut self.menu, ctx, "show bus passengers", "hide bus passengers", @@ -97,10 +98,11 @@ impl GameplayState for OptimizeBus { // TODO Expensive if self.time != ui.primary.sim.time() { self.time = ui.primary.sim.time(); - menu.set_info(ctx, bus_route_panel(self.route, self.stat, ui)); + self.menu + .set_info(ctx, bus_route_panel(self.route, self.stat, ui)); } - if menu.action("change statistic") { + if self.menu.action("change statistic") { return Some(Transition::Push(WizardState::new(Box::new( move |wiz, ctx, _| { // TODO Filter out existing. Make this kind of thing much easier. @@ -127,7 +129,7 @@ impl GameplayState for OptimizeBus { }, )))); } - if menu.action("help") { + if self.menu.action("help") { return Some(Transition::Push(msg( "Help", vec![ @@ -140,6 +142,10 @@ impl GameplayState for OptimizeBus { } None } + + fn draw(&self, g: &mut GfxCtx, _: &UI) { + self.menu.draw(g); + } } fn bus_route_panel(id: BusRouteID, stat: Statistic, ui: &UI) -> Text { diff --git a/game/src/sandbox/gameplay/play_scenario.rs b/game/src/sandbox/gameplay/play_scenario.rs index 5fbd3bd0a0..8ddfeb6505 100644 --- a/game/src/sandbox/gameplay/play_scenario.rs +++ b/game/src/sandbox/gameplay/play_scenario.rs @@ -1,25 +1,16 @@ -use crate::game::{msg, Transition}; +use crate::game::Transition; use crate::managed::Composite; use crate::sandbox::gameplay::freeform::freeform_controller; use crate::sandbox::gameplay::{GameplayMode, GameplayState}; use crate::sandbox::overlays::Overlays; use crate::ui::UI; -use ezgui::{hotkey, EventCtx, Key, ModalMenu}; +use ezgui::{EventCtx, GfxCtx}; pub struct PlayScenario; impl PlayScenario { - pub fn new( - name: &String, - ctx: &mut EventCtx, - ui: &UI, - ) -> (ModalMenu, Composite, Box) { + pub fn new(name: &String, ctx: &mut EventCtx, ui: &UI) -> (Composite, Box) { ( - ModalMenu::new( - format!("Playing {}", name), - vec![(hotkey(Key::H), "help")], - ctx, - ), freeform_controller(ctx, ui, GameplayMode::PlayScenario(name.to_string()), name), Box::new(PlayScenario), ) @@ -27,24 +18,9 @@ impl PlayScenario { } impl GameplayState for PlayScenario { - fn event( - &mut self, - ctx: &mut EventCtx, - _: &mut UI, - _: &mut Overlays, - menu: &mut ModalMenu, - ) -> Option { - menu.event(ctx); - if menu.action("help") { - return Some(Transition::Push(msg( - "Help", - vec![ - "Do things seem a bit quiet?", - "The simulation starts at midnight, so you might need to wait a bit.", - "Try using the speed controls on the left.", - ], - ))); - } + fn event(&mut self, _: &mut EventCtx, _: &mut UI, _: &mut Overlays) -> Option { None } + + fn draw(&self, _: &mut GfxCtx, _: &UI) {} }