make tutorial mode go through its two states again

This commit is contained in:
Dustin Carlino 2018-12-13 14:57:01 -08:00
parent 7c48ec02cc
commit 59c30ac03e
2 changed files with 53 additions and 66 deletions

View File

@ -37,7 +37,7 @@ pub trait UIState {
}
pub struct DefaultUIState {
primary: PerMapUI,
pub primary: PerMapUI,
primary_plugins: PluginsPerMap,
// When running an A/B test, this is populated too.
secondary: Option<(PerMapUI, PluginsPerMap)>,

View File

@ -1,6 +1,5 @@
use crate::colors::ColorScheme;
use crate::objects::{Ctx, RenderingHints, ID};
use crate::plugins::{Plugin, PluginCtx};
use crate::render::Renderable;
use crate::state::{DefaultUIState, UIState};
use crate::ui::PerMapUI;
@ -8,23 +7,34 @@ use ezgui::{Canvas, Color, GfxCtx, LogScroller, UserInput};
use sim::SimFlags;
pub struct TutorialState {
state: DefaultUIState,
main: DefaultUIState,
state: State,
}
enum State {
GiveInstructions(LogScroller),
Play,
}
impl TutorialState {
pub fn new(flags: SimFlags, canvas: &Canvas) -> TutorialState {
TutorialState {
state: DefaultUIState::new(flags, None, canvas),
main: DefaultUIState::new(flags, None, canvas),
state: State::GiveInstructions(LogScroller::new_from_lines(vec![
"Welcome to the A/B Street tutorial!".to_string(),
"".to_string(),
"There'll be some instructions here eventually. Fix all the traffic!".to_string(),
])),
}
}
}
impl UIState for TutorialState {
fn handle_zoom(&mut self, old_zoom: f64, new_zoom: f64) {
self.state.handle_zoom(old_zoom, new_zoom);
self.main.handle_zoom(old_zoom, new_zoom);
}
fn set_current_selection(&mut self, obj: Option<ID>) {
self.state.set_current_selection(obj);
self.main.set_current_selection(obj);
}
fn event(
&mut self,
@ -34,77 +44,54 @@ impl UIState for TutorialState {
cs: &mut ColorScheme,
canvas: &mut Canvas,
) {
self.state
.event(input, hints, recalculate_current_selection, cs, canvas);
match self.state {
State::GiveInstructions(ref mut scroller) => {
if scroller.event(input) {
setup_scenario(&mut self.main.primary);
self.state = State::Play;
}
}
State::Play => {
self.main
.event(input, hints, recalculate_current_selection, cs, canvas);
}
}
}
fn get_objects_onscreen(
&self,
canvas: &Canvas,
) -> (Vec<Box<&Renderable>>, Vec<Box<Renderable>>) {
self.state.get_objects_onscreen(canvas)
self.main.get_objects_onscreen(canvas)
}
fn is_debug_mode_enabled(&self) -> bool {
self.state.is_debug_mode_enabled()
self.main.is_debug_mode_enabled()
}
fn draw(&self, g: &mut GfxCtx, ctx: &Ctx) {
self.state.draw(g, ctx);
}
fn dump_before_abort(&self) {
self.state.dump_before_abort();
}
fn color_obj(&self, id: ID, ctx: &Ctx) -> Option<Color> {
self.state.color_obj(id, ctx)
}
fn primary(&self) -> &PerMapUI {
self.state.primary()
}
}
// TODO Bring this stuff back
pub enum TutorialMode {
GiveInstructions(LogScroller),
Play,
}
impl TutorialMode {
pub fn new() -> TutorialMode {
TutorialMode::GiveInstructions(LogScroller::new_from_lines(vec![
"Welcome to the A/B Street tutorial!".to_string(),
"".to_string(),
"There'll be some instructions here eventually. Fix all the traffic!".to_string(),
]))
}
}
impl Plugin for TutorialMode {
fn blocking_event(&mut self, ctx: &mut PluginCtx) -> bool {
match self {
TutorialMode::GiveInstructions(ref mut scroller) => {
if scroller.event(&mut ctx.input) {
setup_scenario(ctx);
*self = TutorialMode::Play;
}
true
}
TutorialMode::Play => false,
}
}
fn draw(&self, g: &mut GfxCtx, ctx: &Ctx) {
match self {
TutorialMode::GiveInstructions(ref scroller) => {
match self.state {
State::GiveInstructions(ref scroller) => {
scroller.draw(g, ctx.canvas);
}
TutorialMode::Play => {}
};
State::Play => {
self.main.draw(g, ctx);
}
}
}
fn dump_before_abort(&self) {
self.main.dump_before_abort();
}
fn color_obj(&self, id: ID, ctx: &Ctx) -> Option<Color> {
self.main.color_obj(id, ctx)
}
fn primary(&self) -> &PerMapUI {
self.main.primary()
}
}
fn setup_scenario(ctx: &mut PluginCtx) {
fn setup_scenario(primary: &mut PerMapUI) {
use sim::{BorderSpawnOverTime, OriginDestination, Scenario, Tick};
let map = &ctx.primary.map;
let map = &primary.map;
fn border_spawn(ctx: &PluginCtx, from: &str, to: &str) -> BorderSpawnOverTime {
fn border_spawn(primary: &PerMapUI, from: &str, to: &str) -> BorderSpawnOverTime {
BorderSpawnOverTime {
// TODO Can we express something like "100 cars per minute, for an hour"
num_peds: 0,
@ -113,8 +100,8 @@ fn setup_scenario(ctx: &mut PluginCtx) {
percent_use_transit: 0.0,
start_tick: Tick::zero(),
stop_tick: Tick::from_minutes(10),
start_from_border: ctx.primary.map.intersection(from),
goal: OriginDestination::Border(ctx.primary.map.intersection(to)),
start_from_border: primary.map.intersection(from),
goal: OriginDestination::Border(primary.map.intersection(to)),
}
}
@ -126,9 +113,9 @@ fn setup_scenario(ctx: &mut PluginCtx) {
border_spawn_over_time: vec![
// TODO ideally specify the relative spawning rates here, so some sides can be
// imbalanced
border_spawn(ctx, "south", "west"),
border_spawn(ctx, "north", "south"),
border_spawn(primary, "south", "west"),
border_spawn(primary, "north", "south"),
],
}
.instantiate(&mut ctx.primary.sim, map);
.instantiate(&mut primary.sim, map);
}