using trait objects to remove boilerplate

This commit is contained in:
Dustin Carlino 2019-11-07 13:15:59 -08:00
parent 5037b9e077
commit 863213eaf0
6 changed files with 64 additions and 64 deletions

View File

@ -1,6 +1,7 @@
use crate::game::{msg, Transition};
use crate::render::AgentColorScheme;
use crate::sandbox::gameplay::{cmp_count_fewer, manage_acs, State};
use crate::sandbox::gameplay::{cmp_count_fewer, manage_acs, GameplayState};
use crate::sandbox::overlays::Overlays;
use crate::ui::UI;
use abstutil::prettyprint_usize;
use ezgui::{hotkey, EventCtx, Key, Line, ModalMenu, Text};
@ -12,7 +13,7 @@ pub struct CreateGridlock {
}
impl CreateGridlock {
pub fn new(ctx: &EventCtx) -> (ModalMenu, State) {
pub fn new(ctx: &EventCtx) -> (ModalMenu, Box<dyn GameplayState>) {
(
ModalMenu::new(
"Cause gridlock",
@ -22,16 +23,19 @@ impl CreateGridlock {
],
ctx,
),
State::CreateGridlock(CreateGridlock {
Box::new(CreateGridlock {
time: Duration::ZERO,
}),
)
}
}
pub fn event(
impl GameplayState for CreateGridlock {
fn event(
&mut self,
ctx: &mut EventCtx,
ui: &mut UI,
_: &mut Overlays,
menu: &mut ModalMenu,
prebaked: &Analytics,
) -> Option<Transition> {

View File

@ -1,5 +1,6 @@
use crate::game::{msg, Transition};
use crate::sandbox::gameplay::{cmp_count_more, cmp_duration_shorter, State};
use crate::sandbox::gameplay::{cmp_count_more, cmp_duration_shorter, GameplayState};
use crate::sandbox::overlays::Overlays;
use crate::ui::UI;
use abstutil::prettyprint_usize;
use ezgui::{hotkey, EventCtx, Key, Line, ModalMenu, Text};
@ -12,24 +13,27 @@ pub struct FasterTrips {
}
impl FasterTrips {
pub fn new(trip_mode: TripMode, ctx: &EventCtx) -> (ModalMenu, State) {
pub fn new(trip_mode: TripMode, ctx: &EventCtx) -> (ModalMenu, Box<dyn GameplayState>) {
(
ModalMenu::new(
&format!("Speed up {} trips", trip_mode),
vec![(hotkey(Key::H), "help")],
ctx,
),
State::FasterTrips(FasterTrips {
Box::new(FasterTrips {
mode: trip_mode,
time: Duration::ZERO,
}),
)
}
}
pub fn event(
impl GameplayState for FasterTrips {
fn event(
&mut self,
ctx: &mut EventCtx,
ui: &mut UI,
_: &mut Overlays,
menu: &mut ModalMenu,
prebaked: &Analytics,
) -> Option<Transition> {

View File

@ -1,14 +1,16 @@
use crate::game::{msg, Transition, WizardState};
use crate::sandbox::gameplay::{change_scenario, load_map, State};
use crate::sandbox::gameplay::{change_scenario, load_map, GameplayState};
use crate::sandbox::overlays::Overlays;
use crate::sandbox::spawner;
use crate::ui::UI;
use ezgui::{hotkey, lctrl, EventCtx, Key, ModalMenu};
use sim::Analytics;
// TODO Maybe remember what things were spawned, offer to replay this later
pub struct Freeform;
impl Freeform {
pub fn new(ctx: &EventCtx) -> (ModalMenu, State) {
pub fn new(ctx: &EventCtx) -> (ModalMenu, Box<dyn GameplayState>) {
(
ModalMenu::new(
"Freeform mode",
@ -19,15 +21,19 @@ impl Freeform {
],
ctx,
),
State::Freeform(Freeform),
Box::new(Freeform),
)
}
}
pub fn event(
impl GameplayState for Freeform {
fn event(
&mut self,
ctx: &mut EventCtx,
ui: &mut UI,
_: &mut Overlays,
menu: &mut ModalMenu,
_: &Analytics,
) -> Option<Transition> {
menu.event(ctx);
if menu.action("start a scenario") {

View File

@ -17,7 +17,7 @@ use sim::{Analytics, Scenario, TripMode};
pub struct GameplayRunner {
pub mode: GameplayMode,
pub menu: ModalMenu,
state: State,
state: Box<dyn GameplayState>,
prebaked: Analytics,
}
@ -33,13 +33,17 @@ pub enum GameplayMode {
FasterTrips(TripMode),
}
pub enum State {
Freeform(freeform::Freeform),
PlayScenario(play_scenario::PlayScenario),
OptimizeBus(optimize_bus::OptimizeBus),
CreateGridlock(create_gridlock::CreateGridlock),
FasterTrips(faster_trips::FasterTrips),
pub trait GameplayState: downcast_rs::Downcast {
fn event(
&mut self,
ctx: &mut EventCtx,
ui: &mut UI,
overlays: &mut Overlays,
menu: &mut ModalMenu,
analytics: &Analytics,
) -> Option<Transition>;
}
downcast_rs::impl_downcast!(GameplayState);
impl GameplayRunner {
pub fn initialize(mode: GameplayMode, ui: &mut UI, ctx: &mut EventCtx) -> GameplayRunner {
@ -125,34 +129,8 @@ impl GameplayRunner {
ui: &mut UI,
overlays: &mut Overlays,
) -> Option<Transition> {
match self.state {
State::Freeform(ref mut f) => {
if let Some(t) = f.event(ctx, ui, &mut self.menu) {
return Some(t);
}
}
State::PlayScenario(ref mut p) => {
if let Some(t) = p.event(ctx, ui, &mut self.menu) {
return Some(t);
}
}
State::OptimizeBus(ref mut o) => {
if let Some(t) = o.event(ctx, ui, overlays, &mut self.menu, &self.prebaked) {
return Some(t);
}
}
State::CreateGridlock(ref mut g) => {
if let Some(t) = g.event(ctx, ui, &mut self.menu, &self.prebaked) {
return Some(t);
}
}
State::FasterTrips(ref mut f) => {
if let Some(t) = f.event(ctx, ui, &mut self.menu, &self.prebaked) {
return Some(t);
}
}
}
None
self.state
.event(ctx, ui, overlays, &mut self.menu, &self.prebaked)
}
pub fn draw(&self, g: &mut GfxCtx) {

View File

@ -1,7 +1,7 @@
use crate::common::{Plot, Series};
use crate::game::{msg, Transition, WizardState};
use crate::helpers::rotating_color_total;
use crate::sandbox::gameplay::{cmp_duration_shorter, manage_overlays, State};
use crate::sandbox::gameplay::{cmp_duration_shorter, manage_overlays, GameplayState};
use crate::sandbox::overlays::Overlays;
use crate::sandbox::{bus_explorer, SandboxMode};
use crate::ui::UI;
@ -17,7 +17,7 @@ pub struct OptimizeBus {
}
impl OptimizeBus {
pub fn new(route_name: String, ctx: &EventCtx, ui: &UI) -> (ModalMenu, State) {
pub fn new(route_name: String, ctx: &EventCtx, ui: &UI) -> (ModalMenu, Box<dyn GameplayState>) {
let route = ui.primary.map.get_bus_route(&route_name).unwrap();
(
ModalMenu::new(
@ -30,15 +30,17 @@ impl OptimizeBus {
],
ctx,
),
State::OptimizeBus(OptimizeBus {
Box::new(OptimizeBus {
route: route.id,
time: Duration::ZERO,
stat: Statistic::Max,
}),
)
}
}
pub fn event(
impl GameplayState for OptimizeBus {
fn event(
&mut self,
ctx: &mut EventCtx,
ui: &mut UI,
@ -101,14 +103,14 @@ impl OptimizeBus {
)?;
Some(Transition::PopWithData(Box::new(move |state, _, _| {
let sandbox = state.downcast_mut::<SandboxMode>().unwrap();
match sandbox.gameplay.state {
State::OptimizeBus(ref mut o) => {
// Force recalculation
o.time = Duration::ZERO;
o.stat = new_stat;
}
_ => unreachable!(),
}
let opt = sandbox
.gameplay
.state
.downcast_mut::<OptimizeBus>()
.unwrap();
// Force recalculation
opt.time = Duration::ZERO;
opt.stat = new_stat;
})))
},
))));

View File

@ -1,12 +1,14 @@
use crate::game::{msg, Transition, WizardState};
use crate::sandbox::gameplay::{change_scenario, load_map, State};
use crate::sandbox::gameplay::{change_scenario, load_map, GameplayState};
use crate::sandbox::overlays::Overlays;
use crate::ui::UI;
use ezgui::{hotkey, lctrl, EventCtx, Key, ModalMenu};
use sim::Analytics;
pub struct PlayScenario;
impl PlayScenario {
pub fn new(name: &String, ctx: &EventCtx) -> (ModalMenu, State) {
pub fn new(name: &String, ctx: &EventCtx) -> (ModalMenu, Box<dyn GameplayState>) {
(
ModalMenu::new(
&format!("Playing {}", name),
@ -17,15 +19,19 @@ impl PlayScenario {
],
ctx,
),
State::PlayScenario(PlayScenario),
Box::new(PlayScenario),
)
}
}
pub fn event(
impl GameplayState for PlayScenario {
fn event(
&mut self,
ctx: &mut EventCtx,
_ui: &UI,
_: &mut UI,
_: &mut Overlays,
menu: &mut ModalMenu,
_: &Analytics,
) -> Option<Transition> {
menu.event(ctx);
if menu.action("start another scenario") {