also use AgentColorScheme for zoomed color

This commit is contained in:
Dustin Carlino 2019-08-19 13:34:25 -07:00
parent 509936cd43
commit f3f4f98290
11 changed files with 121 additions and 56 deletions

View File

@ -69,6 +69,10 @@ impl CommonState {
choices
})?;
ui.agent_cs = acs;
ui.primary.draw_map.agents.borrow_mut().invalidate_cache();
if let Some(ref mut s) = ui.secondary {
s.draw_map.agents.borrow_mut().invalidate_cache();
}
Some(Transition::Pop)
},
))));

View File

@ -1,9 +1,9 @@
use crate::helpers::{ColorScheme, ID};
use crate::render::{DrawCtx, DrawOptions, Renderable};
use crate::render::{AgentColorScheme, DrawCtx, DrawOptions, Renderable};
use ezgui::{Color, Drawable, GeomBatch, GfxCtx, Prerender};
use geom::{Circle, Distance, Line, PolyLine, Polygon};
use map_model::{Map, LANE_THICKNESS};
use sim::{CarID, CarStatus, DrawCarInput};
use sim::{CarID, DrawCarInput};
pub struct DrawBike {
pub id: CarID,
@ -20,18 +20,13 @@ impl DrawBike {
map: &Map,
prerender: &Prerender,
cs: &ColorScheme,
acs: AgentColorScheme,
) -> DrawBike {
let mut draw_default = GeomBatch::new();
// TODO Share constants with DrawPedestrian
let body_radius = LANE_THICKNESS / 4.0;
let body_color = match input.status {
CarStatus::Debug => cs.get_def("debug bike", Color::BLUE.alpha(0.8)),
// TODO Hard to see on the greenish bike lanes? :P
CarStatus::Moving => cs.get_def("moving bike", Color::GREEN),
CarStatus::Stuck => cs.get_def("stuck bike", Color::RED),
CarStatus::Parked => panic!("Can't have a parked bike {}", input.id),
};
let body_color = acs.zoomed_color_bike(&input, cs);
draw_default.push(
cs.get_def("bike frame", Color::rgb(0, 128, 128)),
input.body.make_polygons(Distance::meters(0.4)),

View File

@ -1,9 +1,9 @@
use crate::helpers::{ColorScheme, ID};
use crate::render::{DrawCtx, DrawOptions, Renderable, OUTLINE_THICKNESS};
use crate::render::{AgentColorScheme, DrawCtx, DrawOptions, Renderable, OUTLINE_THICKNESS};
use ezgui::{Color, Drawable, GeomBatch, GfxCtx, Prerender, Text};
use geom::{Angle, Circle, Distance, PolyLine, Polygon, Pt2D};
use map_model::{Map, TurnType};
use sim::{CarID, CarStatus, DrawCarInput, VehicleType};
use sim::{CarID, DrawCarInput};
const CAR_WIDTH: Distance = Distance::const_meters(2.0);
@ -18,23 +18,17 @@ pub struct DrawCar {
}
impl DrawCar {
pub fn new(input: DrawCarInput, map: &Map, prerender: &Prerender, cs: &ColorScheme) -> DrawCar {
pub fn new(
input: DrawCarInput,
map: &Map,
prerender: &Prerender,
cs: &ColorScheme,
acs: AgentColorScheme,
) -> DrawCar {
let mut draw_default = GeomBatch::new();
let body_polygon = input.body.make_polygons(CAR_WIDTH);
draw_default.push(
if input.id.1 == VehicleType::Bus {
cs.get_def("bus", Color::rgb(50, 133, 117))
} else {
match input.status {
CarStatus::Debug => cs.get_def("debug car", Color::BLUE.alpha(0.8)),
CarStatus::Moving => cs.get_def("moving car", Color::CYAN),
CarStatus::Stuck => cs.get_def("stuck car", Color::rgb(222, 184, 135)),
CarStatus::Parked => cs.get_def("parked car", Color::rgb(180, 233, 76)),
}
},
body_polygon.clone(),
);
draw_default.push(acs.zoomed_color_car(&input, cs), body_polygon.clone());
{
let window_length_gap = Distance::meters(0.2);

View File

@ -17,7 +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 sim::{CarStatus, DrawCarInput, DrawPedestrianInput, UnzoomedAgent, VehicleType};
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::HashMap;
@ -330,8 +330,8 @@ impl DrawMap {
pub struct AgentCache {
time: Option<Duration>,
agents_per_on: HashMap<Traversable, Vec<Box<Renderable>>>,
// cam_zoom and AgentColorScheme also matter
unzoomed: Option<(f64, AgentColorScheme, Drawable)>,
// cam_zoom also matters
unzoomed: Option<(f64, Drawable)>,
}
impl AgentCache {
@ -360,6 +360,12 @@ impl AgentCache {
self.agents_per_on.insert(on, agents);
}
pub fn invalidate_cache(&mut self) {
self.time = None;
self.agents_per_on.clear();
self.unzoomed = None;
}
pub fn draw_unzoomed_agents(
&mut self,
primary: &PerMapUI,
@ -368,8 +374,8 @@ impl AgentCache {
g: &mut GfxCtx,
) {
let now = primary.sim.time();
if let Some((z, old_acs, ref draw)) = self.unzoomed {
if g.canvas.cam_zoom == z && acs == old_acs && Some(now) == self.time {
if let Some((z, ref draw)) = self.unzoomed {
if g.canvas.cam_zoom == z && Some(now) == self.time {
g.redraw(draw);
return;
}
@ -379,14 +385,14 @@ impl AgentCache {
let radius = Distance::meters(10.0) / g.canvas.cam_zoom;
for agent in primary.sim.get_unzoomed_agents(&primary.map) {
batch.push(
acs.color_for(&agent, cs),
acs.unzoomed_color(&agent, cs),
Circle::new(agent.pos, radius).to_polygon(),
);
}
let draw = g.upload(batch);
g.redraw(&draw);
self.unzoomed = Some((g.canvas.cam_zoom, acs, draw));
self.unzoomed = Some((g.canvas.cam_zoom, draw));
if Some(now) != self.time {
self.agents_per_on.clear();
self.time = Some(now);
@ -415,7 +421,7 @@ pub enum AgentColorScheme {
impl Cloneable for AgentColorScheme {}
impl AgentColorScheme {
pub fn color_for(&self, agent: &UnzoomedAgent, cs: &ColorScheme) -> Color {
pub fn unzoomed_color(&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)),
@ -428,6 +434,53 @@ impl AgentColorScheme {
}
}
pub fn zoomed_color_car(&self, input: &DrawCarInput, cs: &ColorScheme) -> Color {
match self {
AgentColorScheme::VehicleTypes => {
if input.id.1 == VehicleType::Bus {
cs.get_def("bus", Color::rgb(50, 133, 117))
} else {
match input.status {
CarStatus::Debug => cs.get_def("debug car", Color::BLUE.alpha(0.8)),
CarStatus::Moving => cs.get_def("moving car", Color::CYAN),
CarStatus::Stuck => cs.get_def("stuck car", Color::rgb(222, 184, 135)),
CarStatus::Parked => cs.get_def("parked car", Color::rgb(180, 233, 76)),
}
}
}
AgentColorScheme::Delay => delay_color(input.time_spent_blocked),
AgentColorScheme::RemainingDistance => percent_color(input.percent_dist_crossed),
}
}
pub fn zoomed_color_bike(&self, input: &DrawCarInput, cs: &ColorScheme) -> Color {
match self {
AgentColorScheme::VehicleTypes => match input.status {
CarStatus::Debug => cs.get_def("debug bike", Color::BLUE.alpha(0.8)),
// TODO Hard to see on the greenish bike lanes? :P
CarStatus::Moving => cs.get_def("moving bike", Color::GREEN),
CarStatus::Stuck => cs.get_def("stuck bike", Color::RED),
CarStatus::Parked => panic!("Can't have a parked bike {}", input.id),
},
AgentColorScheme::Delay => delay_color(input.time_spent_blocked),
AgentColorScheme::RemainingDistance => percent_color(input.percent_dist_crossed),
}
}
pub fn zoomed_color_ped(&self, input: &DrawPedestrianInput, cs: &ColorScheme) -> Color {
match self {
AgentColorScheme::VehicleTypes => {
if input.preparing_bike {
cs.get_def("pedestrian preparing bike", Color::rgb(255, 0, 144))
} else {
cs.get_def("pedestrian", Color::rgb_f(0.2, 0.7, 0.7))
}
}
AgentColorScheme::Delay => delay_color(input.time_spent_blocked),
AgentColorScheme::RemainingDistance => percent_color(input.percent_dist_crossed),
}
}
pub fn all() -> Vec<(AgentColorScheme, String)> {
vec![
(

View File

@ -67,11 +67,12 @@ pub fn draw_vehicle(
map: &Map,
prerender: &Prerender,
cs: &ColorScheme,
acs: AgentColorScheme,
) -> Box<Renderable> {
if input.id.1 == VehicleType::Bike {
Box::new(DrawBike::new(input, map, prerender, cs))
Box::new(DrawBike::new(input, map, prerender, cs, acs))
} else {
Box::new(DrawCar::new(input, map, prerender, cs))
Box::new(DrawCar::new(input, map, prerender, cs, acs))
}
}

View File

@ -1,5 +1,5 @@
use crate::helpers::{ColorScheme, ID};
use crate::render::{DrawCtx, DrawOptions, Renderable, OUTLINE_THICKNESS};
use crate::render::{AgentColorScheme, DrawCtx, DrawOptions, Renderable, OUTLINE_THICKNESS};
use ezgui::{Color, Drawable, GeomBatch, GfxCtx, Prerender, Text};
use geom::{Circle, Distance, PolyLine, Polygon};
use map_model::{Map, LANE_THICKNESS};
@ -20,6 +20,7 @@ impl DrawPedestrian {
map: &Map,
prerender: &Prerender,
cs: &ColorScheme,
acs: AgentColorScheme,
) -> DrawPedestrian {
// TODO Slight issues with rendering small pedestrians:
// - route visualization is thick
@ -122,12 +123,7 @@ impl DrawPedestrian {
let body_circle = Circle::new(input.pos, radius);
let head_circle = Circle::new(input.pos, 0.5 * radius);
let body_color = if input.preparing_bike {
cs.get_def("pedestrian preparing bike", Color::rgb(255, 0, 144))
} else {
cs.get_def("pedestrian", Color::rgb_f(0.2, 0.7, 0.7))
};
draw_default.push(body_color, body_circle.to_polygon());
draw_default.push(acs.zoomed_color_ped(&input, cs), body_circle.to_polygon());
draw_default.push(
cs.get_def("pedestrian head", Color::rgb(139, 69, 19)),
head_circle.to_polygon(),

View File

@ -317,12 +317,17 @@ impl UI {
if !agents.has(time, *on) {
let mut list: Vec<Box<Renderable>> = Vec::new();
for c in source.get_draw_cars(*on, map).into_iter() {
list.push(draw_vehicle(c, map, prerender, &self.cs));
list.push(draw_vehicle(c, map, prerender, &self.cs, self.agent_cs));
}
let (loners, crowds) = source.get_draw_peds(*on, map);
for p in loners {
list.push(Box::new(DrawPedestrian::new(
p, step_count, map, prerender, &self.cs,
p,
step_count,
map,
prerender,
&self.cs,
self.agent_cs,
)));
}
for c in crowds {

View File

@ -57,7 +57,7 @@ impl Car {
pub fn get_draw_car(
&self,
front: Distance,
time: Duration,
now: Duration,
map: &Map,
transit: &TransitSimState,
) -> DrawCarInput {
@ -100,14 +100,15 @@ impl Car {
let body = match self.state {
// Assume the parking lane is to the right of us!
CarState::Unparking(_, ref time_int) => raw_body
.shift_right(LANE_THICKNESS * (1.0 - time_int.percent(time)))
.shift_right(LANE_THICKNESS * (1.0 - time_int.percent(now)))
.unwrap(),
CarState::Parking(_, _, ref time_int) => raw_body
.shift_right(LANE_THICKNESS * time_int.percent(time))
.shift_right(LANE_THICKNESS * time_int.percent(now))
.unwrap(),
_ => raw_body,
};
let path = self.router.get_path();
DrawCarInput {
id: self.vehicle.id,
waiting_for_turn: match self.state {
@ -140,6 +141,11 @@ impl Car {
None
},
body,
time_spent_blocked: self
.blocked_since
.map(|t| now - t)
.unwrap_or(Duration::ZERO),
percent_dist_crossed: path.crossed_so_far() / path.total_length(),
}
}
}

View File

@ -2,7 +2,7 @@ use crate::{CarID, CarStatus, DrawCarInput, ParkedCar, ParkingSpot, Vehicle};
use abstutil::{
deserialize_btreemap, deserialize_multimap, serialize_btreemap, serialize_multimap, MultiMap,
};
use geom::Distance;
use geom::{Distance, Duration};
use map_model;
use map_model::{BuildingID, Lane, LaneID, LaneType, Map, Position, Traversable};
use serde_derive::{Deserialize, Serialize};
@ -108,6 +108,8 @@ impl ParkingSimState {
status: CarStatus::Parked,
on: Traversable::Lane(lane),
label: None,
time_spent_blocked: Duration::ZERO,
percent_dist_crossed: 0.0,
body: map
.get_l(lane)

View File

@ -415,14 +415,14 @@ impl Pedestrian {
}
}
fn get_draw_ped(&self, time: Duration, map: &Map) -> DrawPedestrianInput {
fn get_draw_ped(&self, now: Duration, map: &Map) -> DrawPedestrianInput {
let on = self.path.current_step().as_traversable();
let (pos, facing) = match self.state {
PedState::Crossing(ref dist_int, ref time_int) => {
let percent = if time > time_int.end {
let percent = if now > time_int.end {
1.0
} else {
time_int.percent(time)
time_int.percent(now)
};
let (pos, orig_angle) = on.dist_along(dist_int.lerp(percent), map);
let facing = if dist_int.start < dist_int.end {
@ -452,7 +452,7 @@ impl Pedestrian {
(
front_path
.line
.dist_along(time_int.percent(time) * front_path.line.length())
.dist_along(time_int.percent(now) * front_path.line.length())
.project_away(
LANE_THICKNESS / 4.0,
front_path.line.angle().rotate_degs(90.0),
@ -466,7 +466,7 @@ impl Pedestrian {
front_path
.line
.reverse()
.dist_along(time_int.percent(time) * front_path.line.length())
.dist_along(time_int.percent(now) * front_path.line.length())
.project_away(
LANE_THICKNESS / 4.0,
front_path.line.angle().rotate_degs(-90.0),
@ -475,10 +475,10 @@ impl Pedestrian {
)
}
PedState::StartingToBike(_, ref line, ref time_int) => {
(line.percent_along(time_int.percent(time)), line.angle())
(line.percent_along(time_int.percent(now)), line.angle())
}
PedState::FinishingBiking(_, ref line, ref time_int) => {
(line.percent_along(time_int.percent(time)), line.angle())
(line.percent_along(time_int.percent(now)), line.angle())
}
PedState::WaitingForBus => {
let (pt, angle) = self.goal.sidewalk_pos.pt_and_angle(map);
@ -500,6 +500,11 @@ impl Pedestrian {
_ => false,
},
on,
time_spent_blocked: self
.blocked_since
.map(|t| now - t)
.unwrap_or(Duration::ZERO),
percent_dist_crossed: self.path.crossed_so_far() / self.path.total_length(),
}
}

View File

@ -11,6 +11,8 @@ pub struct DrawPedestrianInput {
pub waiting_for_turn: Option<TurnID>,
pub preparing_bike: bool,
pub on: Traversable,
pub time_spent_blocked: Duration,
pub percent_dist_crossed: f64,
}
pub struct DrawPedCrowdInput {
@ -28,8 +30,10 @@ pub struct DrawCarInput {
pub status: CarStatus,
pub on: Traversable,
pub label: Option<String>,
pub time_spent_blocked: Duration,
pub percent_dist_crossed: f64,
// Starts at the BACK of the car. TODO Dedupe unused old stuff.
// Starts at the BACK of the car.
pub body: PolyLine,
}