make simple model an exclusive blocking plugin, since it otherwise eats keys :)

This commit is contained in:
Dustin Carlino 2019-02-09 13:07:00 -08:00
parent e00d85e1c0
commit f7d3db302d
3 changed files with 95 additions and 112 deletions

View File

@ -1,6 +1,6 @@
use crate::objects::DrawCtx;
use crate::plugins::sim::des_model;
use crate::plugins::PluginCtx;
use crate::plugins::{BlockingPlugin, PluginCtx};
use ezgui::{EventLoopMode, GfxCtx};
use map_model::{Map, Traversable};
use sim::{CarID, DrawCarInput, DrawPedestrianInput, GetDrawAgents, PedestrianID, Tick};
@ -12,102 +12,90 @@ enum AutoMode {
}
pub struct SimpleModelController {
current_tick: Option<Tick>,
world: Option<des_model::World>,
current_tick: Tick,
world: des_model::World,
mode: AutoMode,
show_tooltips: bool,
}
impl SimpleModelController {
pub fn new() -> SimpleModelController {
SimpleModelController {
current_tick: None,
world: None,
mode: AutoMode::Off,
show_tooltips: false,
}
}
pub fn is_active(&self) -> bool {
self.current_tick.is_some()
}
// Don't really need to indicate activeness here.
pub fn event(&mut self, ctx: &mut PluginCtx) {
if let Some(tick) = self.current_tick {
ctx.input.set_mode_with_prompt(
"Simple Model",
format!("Simple Model at {}", tick),
&ctx.canvas,
);
match self.mode {
AutoMode::Off => {
if tick != Tick::zero() && ctx.input.modal_action("rewind") {
self.current_tick = Some(tick.prev());
} else if ctx.input.modal_action("forwards") {
self.current_tick = Some(tick.next());
} else if ctx.input.modal_action("toggle forwards play") {
self.mode = AutoMode::Forwards;
ctx.hints.mode = EventLoopMode::Animation;
} else if ctx.input.modal_action("toggle backwards play") {
self.mode = AutoMode::Backwards;
ctx.hints.mode = EventLoopMode::Animation;
}
}
AutoMode::Forwards => {
ctx.hints.mode = EventLoopMode::Animation;
if ctx.input.modal_action("toggle forwards play") {
self.mode = AutoMode::Off;
} else if ctx.input.is_update_event() {
self.current_tick = Some(tick.next());
}
}
AutoMode::Backwards => {
ctx.hints.mode = EventLoopMode::Animation;
if tick == Tick::zero() || ctx.input.modal_action("toggle backwards play") {
self.mode = AutoMode::Off;
} else if ctx.input.is_update_event() {
self.current_tick = Some(tick.prev());
}
}
}
if ctx.input.modal_action("quit") {
self.current_tick = None;
self.mode = AutoMode::Off;
self.show_tooltips = false;
}
if ctx.input.modal_action("toggle tooltips") {
self.show_tooltips = !self.show_tooltips;
}
} else if ctx.input.action_chosen("start simple model") {
self.current_tick = Some(Tick::zero());
if self.world.is_none() {
self.world = Some(des_model::World::new(&ctx.primary.map));
}
}
}
pub fn draw(&self, g: &mut GfxCtx, ctx: &DrawCtx) {
if self.show_tooltips {
self.world.as_ref().unwrap().draw_tooltips(
g,
ctx,
self.current_tick.unwrap().as_time(),
);
pub fn new(ctx: &mut PluginCtx) -> Option<SimpleModelController> {
if ctx.input.action_chosen("start simple model") {
return Some(SimpleModelController {
current_tick: Tick::zero(),
world: des_model::World::new(&ctx.primary.map),
mode: AutoMode::Off,
show_tooltips: false,
});
}
None
}
fn get_cars(&self, map: &Map) -> Vec<DrawCarInput> {
self.world
.as_ref()
.unwrap()
.get_draw_cars(self.current_tick.unwrap().as_time(), map)
self.world.get_draw_cars(self.current_tick.as_time(), map)
}
}
impl BlockingPlugin for SimpleModelController {
fn blocking_event(&mut self, ctx: &mut PluginCtx) -> bool {
ctx.input.set_mode_with_prompt(
"Simple Model",
format!("Simple Model at {}", self.current_tick),
&ctx.canvas,
);
match self.mode {
AutoMode::Off => {
if self.current_tick != Tick::zero() && ctx.input.modal_action("rewind") {
self.current_tick = self.current_tick.prev();
} else if ctx.input.modal_action("forwards") {
self.current_tick = self.current_tick.next();
} else if ctx.input.modal_action("toggle forwards play") {
self.mode = AutoMode::Forwards;
ctx.hints.mode = EventLoopMode::Animation;
} else if ctx.input.modal_action("toggle backwards play") {
self.mode = AutoMode::Backwards;
ctx.hints.mode = EventLoopMode::Animation;
}
}
AutoMode::Forwards => {
ctx.hints.mode = EventLoopMode::Animation;
if ctx.input.modal_action("toggle forwards play") {
self.mode = AutoMode::Off;
} else if ctx.input.is_update_event() {
self.current_tick = self.current_tick.next();
}
}
AutoMode::Backwards => {
ctx.hints.mode = EventLoopMode::Animation;
if self.current_tick == Tick::zero()
|| ctx.input.modal_action("toggle backwards play")
{
self.mode = AutoMode::Off;
} else if ctx.input.is_update_event() {
self.current_tick = self.current_tick.prev();
}
}
}
if ctx.input.modal_action("quit") {
return false;
}
if ctx.input.modal_action("toggle tooltips") {
self.show_tooltips = !self.show_tooltips;
}
true
}
fn draw(&self, g: &mut GfxCtx, ctx: &DrawCtx) {
if self.show_tooltips {
self.world
.draw_tooltips(g, ctx, self.current_tick.as_time());
}
}
}
impl GetDrawAgents for SimpleModelController {
fn tick(&self) -> Tick {
self.current_tick.unwrap()
self.current_tick
}
fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> {

View File

@ -10,7 +10,7 @@ use abstutil::Timer;
use ezgui::EventCtx;
use ezgui::{Canvas, Color, GfxCtx, Prerender};
use map_model::{IntersectionID, Map};
use sim::{Sim, SimFlags, Tick};
use sim::{GetDrawAgents, Sim, SimFlags, Tick};
use structopt::StructOpt;
#[derive(StructOpt, Debug, Clone)]
@ -48,7 +48,7 @@ pub struct DefaultUIState {
pub secondary: Option<(PerMapUI, PluginsPerMap)>,
// These are all mutually exclusive and, if present, override everything else.
exclusive_blocking_plugin: Option<Box<BlockingPlugin>>,
pub exclusive_blocking_plugin: Option<Box<BlockingPlugin>>,
// These are all mutually exclusive, but don't override other stuff.
exclusive_nonblocking_plugin: Option<Box<NonblockingPlugin>>,
@ -157,6 +157,20 @@ impl DefaultUIState {
}
self.layers.show(obj)
}
pub fn get_draw_agents(&self) -> &GetDrawAgents {
if self.primary_plugins.time_travel.is_active() {
return &self.primary_plugins.time_travel;
}
if let Some(ref plugin) = self.exclusive_blocking_plugin {
if let Ok(p) =
plugin.downcast_ref::<plugins::sim::simple_model::SimpleModelController>()
{
return p;
}
}
&self.primary.sim
}
}
impl UIState for DefaultUIState {
@ -212,11 +226,6 @@ impl UIState for DefaultUIState {
if self.primary_plugins.time_travel.is_active() {
return;
}
// TODO SimpleModelController should be exclusive_blocking_plugin.
self.primary_plugins.simple_model.event(&mut ctx);
if self.primary_plugins.simple_model.is_active() {
return;
}
if self.exclusive_blocking_plugin.is_some() {
if !self
@ -237,6 +246,9 @@ impl UIState for DefaultUIState {
self.primary_plugins.search = Some(p);
} else if let Some(p) = view::warp::WarpState::new(&mut ctx) {
self.exclusive_blocking_plugin = Some(Box::new(p));
} else if let Some(p) = plugins::sim::simple_model::SimpleModelController::new(&mut ctx)
{
self.exclusive_blocking_plugin = Some(Box::new(p));
} else if ctx.secondary.is_none() {
if let Some(p) = edit::a_b_tests::ABTestManager::new(&mut ctx) {
self.exclusive_blocking_plugin = Some(Box::new(p));
@ -424,10 +436,6 @@ impl UIState for DefaultUIState {
}
// Hider doesn't draw
if self.primary_plugins.simple_model.is_active() {
self.primary_plugins.simple_model.draw(g, ctx);
}
// Layers doesn't draw
for p in &self.primary_plugins.ambient_plugins {
p.draw(g, ctx);
@ -487,9 +495,8 @@ pub struct PluginsPerMap {
search: Option<view::search::SearchState>,
// This acts like exclusive blocking when active.
// TODO Make these two implement one of the traits.
// TODO Make this implement one of the traits.
pub time_travel: plugins::sim::time_travel::TimeTravel,
pub simple_model: plugins::sim::simple_model::SimpleModelController,
ambient_plugins: Vec<Box<AmbientPlugin>>,
}
@ -515,7 +522,6 @@ impl PluginsPerMap {
Box::new(view::turn_cycler::TurnCyclerState::new()),
],
time_travel: plugins::sim::time_travel::TimeTravel::new(),
simple_model: plugins::sim::simple_model::SimpleModelController::new(),
};
if enable_debug_controls {
p.ambient_plugins

View File

@ -11,7 +11,6 @@ use geom::{Bounds, Circle, Distance};
use kml;
use map_model::{BuildingID, LaneID, Traversable};
use serde_derive::{Deserialize, Serialize};
use sim::GetDrawAgents;
use std::collections::HashSet;
use std::process;
@ -465,26 +464,16 @@ impl<S: UIState> UI<S> {
// Expand all of the Traversables into agents, populating the cache if needed.
{
let sim: &GetDrawAgents = {
let tt = &state.primary_plugins.time_travel;
let sm = &state.primary_plugins.simple_model;
if tt.is_active() {
tt
} else if sm.is_active() {
sm
} else {
&state.primary.sim
}
};
let tick = sim.tick();
let source = state.get_draw_agents();
let tick = source.tick();
for on in &agents_on {
if !agents.has(tick, *on) {
let mut list: Vec<Box<Renderable>> = Vec::new();
for c in sim.get_draw_cars(*on, map).into_iter() {
for c in source.get_draw_cars(*on, map).into_iter() {
list.push(draw_vehicle(c, map, prerender, &state.cs));
}
for p in sim.get_draw_peds(*on, map).into_iter() {
for p in source.get_draw_peds(*on, map).into_iter() {
list.push(Box::new(DrawPedestrian::new(p, map, prerender, &state.cs)));
}
agents.put(tick, *on, list);