mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-29 17:34:58 +03:00
also use AgentColorScheme for zoomed color
This commit is contained in:
parent
509936cd43
commit
f3f4f98290
@ -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)
|
||||
},
|
||||
))));
|
||||
|
@ -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)),
|
||||
|
@ -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);
|
||||
|
@ -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![
|
||||
(
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user