mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-26 07:52:05 +03:00
using trait objects to remove boilerplate
This commit is contained in:
parent
5037b9e077
commit
863213eaf0
@ -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> {
|
||||
|
@ -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> {
|
||||
|
@ -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") {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
})))
|
||||
},
|
||||
))));
|
||||
|
@ -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") {
|
||||
|
Loading…
Reference in New Issue
Block a user