give ownership of the top-center panel to each gameplay state

This commit is contained in:
Dustin Carlino 2020-01-30 11:01:40 -08:00
parent 78344ee2a4
commit 92c6b8e282
7 changed files with 139 additions and 110 deletions

View File

@ -1,6 +1,6 @@
use crate::game::Transition;
use crate::helpers::cmp_count_fewer;
use crate::managed::WrappedComposite;
use crate::managed::{WrappedComposite, WrappedOutcome};
use crate::render::InnerAgentColorScheme;
use crate::sandbox::gameplay::{challenge_controller, manage_acs, GameplayMode, GameplayState};
use crate::ui::UI;
@ -12,23 +12,34 @@ use sim::TripMode;
pub struct CreateGridlock {
time: Time,
menu: ModalMenu,
top_center: WrappedComposite,
}
impl CreateGridlock {
pub fn new(ctx: &mut EventCtx) -> (WrappedComposite, Box<dyn GameplayState>) {
(
challenge_controller(ctx, GameplayMode::CreateGridlock, "Gridlock Challenge"),
Box::new(CreateGridlock {
time: Time::START_OF_DAY,
menu: ModalMenu::new("", vec![(hotkey(Key::E), "show agent delay")], ctx)
.set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)),
}),
)
pub fn new(ctx: &mut EventCtx) -> Box<dyn GameplayState> {
Box::new(CreateGridlock {
time: Time::START_OF_DAY,
menu: ModalMenu::new("", vec![(hotkey(Key::E), "show agent delay")], ctx)
.set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)),
top_center: challenge_controller(
ctx,
GameplayMode::CreateGridlock,
"Gridlock Challenge",
),
})
}
}
impl GameplayState for CreateGridlock {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
match self.top_center.event(ctx, ui) {
Some(WrappedOutcome::Transition(t)) => {
return Some(t);
}
Some(WrappedOutcome::Clicked(_)) => unreachable!(),
None => {}
}
self.menu.event(ctx);
manage_acs(
&mut self.menu,
@ -48,6 +59,7 @@ impl GameplayState for CreateGridlock {
}
fn draw(&self, g: &mut GfxCtx, _: &UI) {
self.top_center.draw(g);
self.menu.draw(g);
}
}

View File

@ -1,6 +1,6 @@
use crate::game::Transition;
use crate::helpers::{cmp_count_more, cmp_duration_shorter};
use crate::managed::WrappedComposite;
use crate::managed::{WrappedComposite, WrappedOutcome};
use crate::sandbox::gameplay::{challenge_controller, GameplayMode, GameplayState};
use crate::ui::UI;
use abstutil::prettyprint_usize;
@ -12,31 +12,34 @@ pub struct FasterTrips {
mode: TripMode,
time: Time,
menu: ModalMenu,
top_center: WrappedComposite,
}
impl FasterTrips {
pub fn new(
trip_mode: TripMode,
ctx: &mut EventCtx,
) -> (WrappedComposite, Box<dyn GameplayState>) {
(
challenge_controller(
pub fn new(trip_mode: TripMode, ctx: &mut EventCtx) -> Box<dyn GameplayState> {
Box::new(FasterTrips {
mode: trip_mode,
time: Time::START_OF_DAY,
menu: ModalMenu::new::<&str, &str>("", Vec::new(), ctx)
.set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)),
top_center: challenge_controller(
ctx,
GameplayMode::FasterTrips(trip_mode),
&format!("Faster {} Trips Challenge", trip_mode),
),
Box::new(FasterTrips {
mode: trip_mode,
time: Time::START_OF_DAY,
menu: ModalMenu::new::<&str, &str>("", Vec::new(), ctx)
.set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)),
}),
)
})
}
}
impl GameplayState for FasterTrips {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
match self.top_center.event(ctx, ui) {
Some(WrappedOutcome::Transition(t)) => {
return Some(t);
}
Some(WrappedOutcome::Clicked(_)) => unreachable!(),
None => {}
}
self.menu.event(ctx);
if self.time != ui.primary.sim.time() {
@ -48,6 +51,7 @@ impl GameplayState for FasterTrips {
}
fn draw(&self, g: &mut GfxCtx, _: &UI) {
self.top_center.draw(g);
self.menu.draw(g);
}
}

View File

@ -1,7 +1,7 @@
use crate::common::Overlays;
use crate::game::{msg, Transition};
use crate::helpers::cmp_duration_shorter;
use crate::managed::WrappedComposite;
use crate::managed::{WrappedComposite, WrappedOutcome};
use crate::sandbox::gameplay::{
challenge_controller, manage_overlays, GameplayMode, GameplayState,
};
@ -15,30 +15,26 @@ pub struct FixTrafficSignals {
time: Time,
once: bool,
menu: ModalMenu,
top_center: WrappedComposite,
}
impl FixTrafficSignals {
pub fn new(
ctx: &mut EventCtx,
mode: GameplayMode,
) -> (WrappedComposite, Box<dyn GameplayState>) {
(
challenge_controller(ctx, mode, "Traffic Signals Challenge"),
Box::new(FixTrafficSignals {
time: Time::START_OF_DAY,
once: true,
menu: ModalMenu::new(
"",
vec![
(hotkey(Key::F), "find slowest traffic signals"),
(hotkey(Key::D), "hide finished trip distribution"),
(hotkey(Key::S), "final score"),
],
ctx,
)
.set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)),
}),
)
pub fn new(ctx: &mut EventCtx, mode: GameplayMode) -> Box<dyn GameplayState> {
Box::new(FixTrafficSignals {
time: Time::START_OF_DAY,
once: true,
menu: ModalMenu::new(
"",
vec![
(hotkey(Key::F), "find slowest traffic signals"),
(hotkey(Key::D), "hide finished trip distribution"),
(hotkey(Key::S), "final score"),
],
ctx,
)
.set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)),
top_center: challenge_controller(ctx, mode, "Traffic Signals Challenge"),
})
}
}
@ -50,6 +46,13 @@ impl GameplayState for FixTrafficSignals {
self.once = false;
}
match self.top_center.event(ctx, ui) {
Some(WrappedOutcome::Transition(t)) => {
return Some(t);
}
Some(WrappedOutcome::Clicked(_)) => unreachable!(),
None => {}
}
self.menu.event(ctx);
// Technically this shows stop signs too, but mostly the bottlenecks are signals.
@ -111,6 +114,7 @@ impl GameplayState for FixTrafficSignals {
}
fn draw(&self, g: &mut GfxCtx, _: &UI) {
self.top_center.draw(g);
self.menu.draw(g);
}
}

View File

@ -1,7 +1,7 @@
use crate::edit::EditMode;
use crate::game::{State, Transition, WizardState};
use crate::helpers::{nice_map_name, ID};
use crate::managed::WrappedComposite;
use crate::managed::{WrappedComposite, WrappedOutcome};
use crate::sandbox::gameplay::{change_scenario, spawner, GameplayMode, GameplayState};
use crate::sandbox::SandboxMode;
use crate::ui::UI;
@ -17,21 +17,28 @@ use std::collections::BTreeSet;
pub struct Freeform {
// TODO Clean these up later when done?
pub spawn_pts: BTreeSet<IntersectionID>,
top_center: WrappedComposite,
}
impl Freeform {
pub fn new(ctx: &mut EventCtx, ui: &UI) -> (WrappedComposite, Box<dyn GameplayState>) {
(
freeform_controller(ctx, ui, GameplayMode::Freeform, "none"),
Box::new(Freeform {
spawn_pts: BTreeSet::new(),
}),
)
pub fn new(ctx: &mut EventCtx, ui: &UI) -> Box<dyn GameplayState> {
Box::new(Freeform {
spawn_pts: BTreeSet::new(),
top_center: freeform_controller(ctx, ui, GameplayMode::Freeform, "none"),
})
}
}
impl GameplayState for Freeform {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
match self.top_center.event(ctx, ui) {
Some(WrappedOutcome::Transition(t)) => {
return Some(t);
}
Some(WrappedOutcome::Clicked(_)) => unreachable!(),
None => {}
}
if let Some(new_state) = spawner::AgentSpawner::new(ctx, ui) {
return Some(Transition::Push(new_state));
}
@ -42,6 +49,7 @@ impl GameplayState for Freeform {
}
fn draw(&self, g: &mut GfxCtx, ui: &UI) {
self.top_center.draw(g);
// TODO Overriding draw options would be ideal, but...
for i in &self.spawn_pts {
g.draw_polygon(Color::GREEN.alpha(0.8), &ui.primary.map.get_i(*i).polygon);

View File

@ -10,7 +10,7 @@ use crate::challenges;
use crate::common::Overlays;
use crate::edit::EditMode;
use crate::game::{msg, Transition};
use crate::managed::{WrappedComposite, WrappedOutcome};
use crate::managed::WrappedComposite;
use crate::render::{AgentColorScheme, InnerAgentColorScheme};
use crate::sandbox::SandboxMode;
use crate::ui::UI;
@ -25,8 +25,6 @@ use sim::{Analytics, Scenario, TripMode};
pub struct GameplayRunner {
pub mode: GameplayMode,
// TODO Why not make each state own this?
controller: WrappedComposite,
state: Box<dyn GameplayState>,
}
@ -137,7 +135,7 @@ impl GameplayMode {
impl GameplayRunner {
pub fn initialize(mode: GameplayMode, ui: &mut UI, ctx: &mut EventCtx) -> GameplayRunner {
let (controller, state) = match mode.clone() {
let state = match mode.clone() {
GameplayMode::Freeform => freeform::Freeform::new(ctx, ui),
GameplayMode::PlayScenario(scenario) => {
play_scenario::PlayScenario::new(&scenario, ctx, ui)
@ -186,26 +184,14 @@ impl GameplayRunner {
}
}
});
GameplayRunner {
mode,
controller,
state,
}
GameplayRunner { mode, state }
}
pub fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
match self.controller.event(ctx, ui) {
Some(WrappedOutcome::Transition(t)) => {
return Some(t);
}
Some(WrappedOutcome::Clicked(_)) => unreachable!(),
None => {}
}
self.state.event(ctx, ui)
}
pub fn draw(&self, g: &mut GfxCtx, ui: &UI) {
self.controller.draw(g);
self.state.draw(g, ui);
}
}
@ -298,7 +284,7 @@ fn manage_acs(
}
}
pub fn challenge_controller(
fn challenge_controller(
ctx: &mut EventCtx,
gameplay: GameplayMode,
title: &str,

View File

@ -1,7 +1,7 @@
use crate::common::Overlays;
use crate::game::{Transition, WizardState};
use crate::helpers::cmp_duration_shorter;
use crate::managed::WrappedComposite;
use crate::managed::{WrappedComposite, WrappedOutcome};
use crate::sandbox::gameplay::{
challenge_controller, manage_overlays, GameplayMode, GameplayState,
};
@ -16,43 +16,45 @@ pub struct OptimizeBus {
time: Time,
stat: Statistic,
menu: ModalMenu,
top_center: WrappedComposite,
}
impl OptimizeBus {
pub fn new(
route_name: String,
ctx: &mut EventCtx,
ui: &UI,
) -> (WrappedComposite, Box<dyn GameplayState>) {
pub fn new(route_name: String, ctx: &mut EventCtx, ui: &UI) -> Box<dyn GameplayState> {
let route = ui.primary.map.get_bus_route(&route_name).unwrap();
(
challenge_controller(
Box::new(OptimizeBus {
route: route.id,
time: Time::START_OF_DAY,
stat: Statistic::Max,
menu: ModalMenu::new(
"",
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"),
],
ctx,
)
.set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)),
top_center: challenge_controller(
ctx,
GameplayMode::OptimizeBus(route_name.clone()),
&format!("Optimize {} Challenge", route_name),
),
Box::new(OptimizeBus {
route: route.id,
time: Time::START_OF_DAY,
stat: Statistic::Max,
menu: ModalMenu::new(
"",
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"),
],
ctx,
)
.set_standalone_layout(layout::ContainerOrientation::TopLeftButDownABit(150.0)),
}),
)
})
}
}
impl GameplayState for OptimizeBus {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
match self.top_center.event(ctx, ui) {
Some(WrappedOutcome::Transition(t)) => {
return Some(t);
}
Some(WrappedOutcome::Clicked(_)) => unreachable!(),
None => {}
}
self.menu.event(ctx);
if manage_overlays(
&mut self.menu,
@ -132,6 +134,7 @@ impl GameplayState for OptimizeBus {
}
fn draw(&self, g: &mut GfxCtx, _: &UI) {
self.top_center.draw(g);
self.menu.draw(g);
}
}

View File

@ -1,29 +1,41 @@
use crate::game::Transition;
use crate::managed::WrappedComposite;
use crate::managed::{WrappedComposite, WrappedOutcome};
use crate::sandbox::gameplay::freeform::freeform_controller;
use crate::sandbox::gameplay::{GameplayMode, GameplayState};
use crate::ui::UI;
use ezgui::{EventCtx, GfxCtx};
pub struct PlayScenario;
pub struct PlayScenario {
top_center: WrappedComposite,
}
impl PlayScenario {
pub fn new(
name: &String,
ctx: &mut EventCtx,
ui: &UI,
) -> (WrappedComposite, Box<dyn GameplayState>) {
(
freeform_controller(ctx, ui, GameplayMode::PlayScenario(name.to_string()), name),
Box::new(PlayScenario),
)
pub fn new(name: &String, ctx: &mut EventCtx, ui: &UI) -> Box<dyn GameplayState> {
Box::new(PlayScenario {
top_center: freeform_controller(
ctx,
ui,
GameplayMode::PlayScenario(name.to_string()),
name,
),
})
}
}
impl GameplayState for PlayScenario {
fn event(&mut self, _: &mut EventCtx, _: &mut UI) -> Option<Transition> {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
match self.top_center.event(ctx, ui) {
Some(WrappedOutcome::Transition(t)) => {
return Some(t);
}
Some(WrappedOutcome::Clicked(_)) => unreachable!(),
None => {}
}
None
}
fn draw(&self, _: &mut GfxCtx, _: &UI) {}
fn draw(&self, g: &mut GfxCtx, _: &UI) {
self.top_center.draw(g);
}
}