making all AgentColorScheme values work the same, with the same caching

This commit is contained in:
Dustin Carlino 2019-08-18 14:41:56 -07:00
parent 266dc0238d
commit dd28afcd29
7 changed files with 76 additions and 86 deletions

View File

@ -16,29 +16,18 @@ pub use self::speed::SpeedControls;
pub use self::time::time_controls;
pub use self::trip_explorer::TripExplorer;
use crate::game::Transition;
use crate::helpers::{rotating_color, ID};
use crate::render::{DrawOptions, MIN_ZOOM_FOR_DETAIL};
use crate::helpers::ID;
use crate::render::{AgentColorScheme, DrawOptions};
use crate::ui::UI;
use ezgui::{
Color, EventCtx, EventLoopMode, GeomBatch, GfxCtx, HorizontalAlignment, ModalMenu, Text,
VerticalAlignment,
Color, EventCtx, EventLoopMode, GfxCtx, HorizontalAlignment, ModalMenu, Text, VerticalAlignment,
};
use geom::{Circle, Distance, Duration};
use std::collections::BTreeSet;
pub struct CommonState {
associated: associated::ShowAssociatedState,
turn_cycler: turn_cycler::TurnCyclerState,
agent_colors: AgentColorScheme,
}
// TODO Have a more general colorscheme that can be changed and affect everything. Show a little
// legend when it's first activated.
#[derive(Clone, Copy, PartialEq)]
enum AgentColorScheme {
VehicleTypes,
Delay,
RemainingDistance,
agent_cs: AgentColorScheme,
}
impl CommonState {
@ -46,7 +35,7 @@ impl CommonState {
CommonState {
associated: associated::ShowAssociatedState::Inactive,
turn_cycler: turn_cycler::TurnCyclerState::Inactive,
agent_colors: AgentColorScheme::VehicleTypes,
agent_cs: AgentColorScheme::VehicleTypes,
}
}
@ -69,14 +58,14 @@ impl CommonState {
// This kind of belongs in AgentTools, except that can't influence DrawOptions as easily.
// TODO This needs to be a mutex radio button style thing.
if menu.action("show/hide delayed traffic") {
self.agent_colors = match self.agent_colors {
self.agent_cs = match self.agent_cs {
AgentColorScheme::VehicleTypes => AgentColorScheme::Delay,
AgentColorScheme::Delay => AgentColorScheme::VehicleTypes,
x => x,
};
}
if menu.action("show/hide distance remaining") {
self.agent_colors = match self.agent_colors {
self.agent_cs = match self.agent_cs {
AgentColorScheme::VehicleTypes => AgentColorScheme::RemainingDistance,
AgentColorScheme::RemainingDistance => AgentColorScheme::VehicleTypes,
x => x,
@ -99,30 +88,6 @@ impl CommonState {
pub fn draw(&self, g: &mut GfxCtx, ui: &UI) {
self.turn_cycler.draw(g, ui);
if self.agent_colors != AgentColorScheme::VehicleTypes
&& g.canvas.cam_zoom < MIN_ZOOM_FOR_DETAIL
{
let mut batch = GeomBatch::new();
let radius = Distance::meters(10.0) / g.canvas.cam_zoom;
for agent in ui
.primary
.sim
.get_unzoomed_agents_with_details(&ui.primary.map)
{
batch.push(
match self.agent_colors {
AgentColorScheme::VehicleTypes => unreachable!(),
AgentColorScheme::Delay => delay_color(agent.time_spent_blocked),
AgentColorScheme::RemainingDistance => {
percent_color(agent.percent_dist_crossed)
}
},
Circle::new(agent.pos, radius).to_polygon(),
);
}
batch.draw(g);
}
CommonState::draw_osd(g, ui, &ui.primary.current_selection);
}
@ -220,25 +185,10 @@ impl CommonState {
let mut opts = DrawOptions::new();
self.associated
.override_colors(&mut opts.override_colors, ui);
opts.agent_cs = self.agent_cs;
opts.suppress_traffic_signal_details = self
.turn_cycler
.suppress_traffic_signal_details(&ui.primary.map);
opts.suppress_unzoomed_agents = self.agent_colors != AgentColorScheme::VehicleTypes;
opts
}
}
fn delay_color(delay: Duration) -> Color {
// TODO Better gradient
if delay <= Duration::minutes(1) {
return Color::BLUE.alpha(0.3);
}
if delay <= Duration::minutes(5) {
return Color::ORANGE.alpha(0.5);
}
Color::RED.alpha(0.8)
}
fn percent_color(percent: f64) -> Color {
rotating_color((percent * 10.0).round() as usize)
}

View File

@ -1,4 +1,4 @@
use crate::helpers::{ColorScheme, ID};
use crate::helpers::{rotating_color, ColorScheme, ID};
use crate::render::area::DrawArea;
use crate::render::building::DrawBuilding;
use crate::render::bus_stop::DrawBusStop;
@ -17,6 +17,7 @@ use map_model::{
AreaID, BuildingID, BusStopID, DirectedRoadID, IntersectionID, IntersectionType, Lane, LaneID,
Map, RoadID, Traversable, Turn, TurnID, TurnType, LANE_THICKNESS,
};
use sim::{UnzoomedAgent, VehicleType};
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::HashMap;
@ -326,11 +327,11 @@ impl DrawMap {
}
}
// TODO Invalidate when we interactively spawn stuff elsewhere?
pub struct AgentCache {
time: Option<Duration>,
agents_per_on: HashMap<Traversable, Vec<Box<Renderable>>>,
unzoomed: Option<(f64, Drawable)>,
// cam_zoom and AgentColorScheme also matter
unzoomed: Option<(f64, AgentColorScheme, Drawable)>,
}
impl AgentCache {
@ -359,35 +360,33 @@ impl AgentCache {
self.agents_per_on.insert(on, agents);
}
pub fn draw_unzoomed_agents(&mut self, primary: &PerMapUI, cs: &ColorScheme, g: &mut GfxCtx) {
pub fn draw_unzoomed_agents(
&mut self,
primary: &PerMapUI,
acs: AgentColorScheme,
cs: &ColorScheme,
g: &mut GfxCtx,
) {
let now = primary.sim.time();
if let Some((z, ref draw)) = self.unzoomed {
if g.canvas.cam_zoom == z && Some(now) == self.time {
if let Some((z, old_acs, ref draw)) = self.unzoomed {
if g.canvas.cam_zoom == z && acs == old_acs && Some(now) == self.time {
g.redraw(draw);
return;
}
}
let (cars, bikes, buses, peds) = primary.sim.get_unzoomed_agents(&primary.map);
let mut batch = GeomBatch::new();
let radius = Distance::meters(10.0) / g.canvas.cam_zoom;
for (color, agents) in vec![
(cs.get_def("unzoomed car", Color::RED.alpha(0.5)), cars),
(cs.get_def("unzoomed bike", Color::GREEN.alpha(0.5)), bikes),
(cs.get_def("unzoomed bus", Color::BLUE.alpha(0.5)), buses),
(
cs.get_def("unzoomed pedestrian", Color::ORANGE.alpha(0.5)),
peds,
),
] {
for pt in agents {
batch.push(color, Circle::new(pt, radius).to_polygon());
}
for agent in primary.sim.get_unzoomed_agents_with_details(&primary.map) {
batch.push(
acs.color_for(&agent, cs),
Circle::new(agent.pos, radius).to_polygon(),
);
}
let draw = g.upload(batch);
g.redraw(&draw);
self.unzoomed = Some((g.canvas.cam_zoom, draw));
self.unzoomed = Some((g.canvas.cam_zoom, acs, draw));
if Some(now) != self.time {
self.agents_per_on.clear();
self.time = Some(now);
@ -404,3 +403,42 @@ fn osm_rank_to_color(cs: &ColorScheme, rank: usize) -> Color {
cs.get_def("unzoomed residential road", Color::WHITE)
}
}
// TODO Have a more general colorscheme that can be changed and affect everything. Show a little
// legend when it's first activated.
#[derive(Clone, Copy, PartialEq)]
pub enum AgentColorScheme {
VehicleTypes,
Delay,
RemainingDistance,
}
impl AgentColorScheme {
pub fn color_for(&self, agent: &UnzoomedAgent, cs: &ColorScheme) -> Color {
match self {
AgentColorScheme::VehicleTypes => match agent.vehicle_type {
Some(VehicleType::Car) => cs.get_def("unzoomed car", Color::RED.alpha(0.5)),
Some(VehicleType::Bike) => cs.get_def("unzoomed bike", Color::GREEN.alpha(0.5)),
Some(VehicleType::Bus) => cs.get_def("unzoomed bus", Color::BLUE.alpha(0.5)),
None => cs.get_def("unzoomed pedestrian", Color::ORANGE.alpha(0.5)),
},
AgentColorScheme::Delay => delay_color(agent.time_spent_blocked),
AgentColorScheme::RemainingDistance => percent_color(agent.percent_dist_crossed),
}
}
}
fn delay_color(delay: Duration) -> Color {
// TODO Better gradient
if delay <= Duration::minutes(1) {
return Color::BLUE.alpha(0.3);
}
if delay <= Duration::minutes(5) {
return Color::ORANGE.alpha(0.5);
}
Color::RED.alpha(0.8)
}
fn percent_color(percent: f64) -> Color {
rotating_color((percent * 10.0).round() as usize)
}

View File

@ -19,7 +19,7 @@ use crate::render::car::DrawCar;
pub use crate::render::extra_shape::ExtraShapeID;
pub use crate::render::intersection::{calculate_corners, DrawIntersection};
pub use crate::render::lane::DrawLane;
pub use crate::render::map::{AgentCache, DrawMap};
pub use crate::render::map::{AgentCache, AgentColorScheme, DrawMap};
pub use crate::render::pedestrian::{DrawPedCrowd, DrawPedestrian};
pub use crate::render::road::DrawRoad;
pub use crate::render::traffic_signal::{draw_signal_cycle, TrafficSignalDiagram};
@ -86,9 +86,9 @@ pub struct DrawOptions {
pub override_colors: HashMap<ID, Color>,
pub suppress_traffic_signal_details: Option<IntersectionID>,
pub geom_debug_mode: bool,
pub suppress_unzoomed_agents: bool,
pub label_buildings: bool,
pub label_roads: bool,
pub agent_cs: AgentColorScheme,
}
impl DrawOptions {
@ -97,9 +97,9 @@ impl DrawOptions {
override_colors: HashMap::new(),
suppress_traffic_signal_details: None,
geom_debug_mode: false,
suppress_unzoomed_agents: false,
label_buildings: false,
label_roads: false,
agent_cs: AgentColorScheme::VehicleTypes,
}
}

View File

@ -125,10 +125,8 @@ impl UI {
);
}
if !opts.suppress_unzoomed_agents {
let mut cache = self.primary.draw_map.agents.borrow_mut();
cache.draw_unzoomed_agents(&self.primary, &self.cs, g);
}
let mut cache = self.primary.draw_map.agents.borrow_mut();
cache.draw_unzoomed_agents(&self.primary, opts.agent_cs, &self.cs, g);
} else {
let mut cache = self.primary.draw_map.agents.borrow_mut();
let objects = self.get_renderables_back_to_front(

View File

@ -699,6 +699,7 @@ impl DrivingSimState {
let car = &self.cars[&c];
let path = car.router.get_path();
result.push(UnzoomedAgent {
vehicle_type: Some(car.vehicle.vehicle_type),
pos: queue.id.dist_along(dist, map).0,
time_spent_blocked: car
.blocked_since

View File

@ -277,6 +277,7 @@ impl WalkingSimState {
for ped in self.peds.values() {
peds.push(UnzoomedAgent {
vehicle_type: None,
pos: ped.get_draw_ped(now, map).pos,
time_spent_blocked: ped.blocked_since.map(|t| now - t).unwrap_or(Duration::ZERO),
percent_dist_crossed: ped.path.crossed_so_far() / ped.path.total_length(),

View File

@ -1,4 +1,4 @@
use crate::{CarID, PedestrianID};
use crate::{CarID, PedestrianID, VehicleType};
use geom::{Angle, Distance, Duration, PolyLine, Pt2D};
use map_model::{Map, Traversable, TurnID};
@ -42,6 +42,8 @@ pub enum CarStatus {
}
pub struct UnzoomedAgent {
// None means a pedestrian.
pub vehicle_type: Option<VehicleType>,
pub pos: Pt2D,
pub time_spent_blocked: Duration,
pub percent_dist_crossed: f64,