mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-29 17:34:58 +03:00
making all AgentColorScheme values work the same, with the same caching
This commit is contained in:
parent
266dc0238d
commit
dd28afcd29
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user