when an info panel is open, keep an outline on the object. dont quite

handle peds <-> crowds
This commit is contained in:
Dustin Carlino 2020-01-24 12:59:34 -08:00
parent ffdde86fc6
commit 6452953370
4 changed files with 101 additions and 38 deletions

View File

@ -20,6 +20,8 @@ pub struct InfoPanel {
pub time: Time,
pub composite: Composite,
also_draw: Drawable,
// (unzoomed, zoomed)
trip_details: Option<(Drawable, Drawable)>,
actions: Vec<(Key, String)>,
@ -136,6 +138,20 @@ impl InfoPanel {
ctx.canvas.center_on_map_pt(pt);
}
let mut batch = GeomBatch::new();
// TODO Handle transitions between peds and crowds better
if let Some(obj) = ui.primary.draw_map.get_obj(
id.clone(),
ui,
&mut ui.primary.draw_map.agents.borrow_mut(),
ctx.prerender,
) {
batch.push(
ui.cs.get_def("current object", Color::BLUE),
obj.get_outline(&ui.primary.map),
);
}
InfoPanel {
id,
actions,
@ -148,6 +164,7 @@ impl InfoPanel {
)
.max_size_percent(40, 60)
.build(ctx),
also_draw: batch.upload(ctx),
}
}
@ -180,6 +197,7 @@ impl InfoPanel {
);
}
}
// TODO Detect crowds changing here maybe
let preserve_scroll = self.composite.preserve_scroll();
*self = InfoPanel::new(self.id.clone(), ctx, ui, self.actions.clone(), maybe_speed);
@ -223,6 +241,7 @@ impl InfoPanel {
g.redraw(zoomed);
}
}
g.redraw(&self.also_draw);
}
}

View File

@ -6,11 +6,11 @@ use crate::render::extra_shape::{DrawExtraShape, ExtraShapeID};
use crate::render::intersection::DrawIntersection;
use crate::render::lane::DrawLane;
use crate::render::road::DrawRoad;
use crate::render::Renderable;
use crate::ui::Flags;
use crate::render::{draw_vehicle, DrawPedCrowd, DrawPedestrian, Renderable};
use crate::ui::{Flags, UI};
use aabb_quadtree::QuadTree;
use abstutil::{Cloneable, Timer};
use ezgui::{Color, Drawable, EventCtx, GeomBatch, GfxCtx};
use ezgui::{Color, Drawable, EventCtx, GeomBatch, GfxCtx, Prerender};
use geom::{Bounds, Circle, Distance, Duration, FindClosest, Time};
use map_model::{
AreaID, BuildingID, BusStopID, DirectedRoadID, Intersection, IntersectionID, LaneID, Map, Road,
@ -281,6 +281,52 @@ impl DrawMap {
&self.areas[id.0]
}
pub fn get_obj<'a>(
&'a self,
id: ID,
ui: &UI,
agents: &'a mut AgentCache,
prerender: &Prerender,
) -> Option<&'a dyn Renderable> {
let on = match id {
ID::Road(id) => {
return Some(self.get_r(id));
}
ID::Lane(id) => {
return Some(self.get_l(id));
}
ID::Intersection(id) => {
return Some(self.get_i(id));
}
ID::Turn(_) => unreachable!(),
ID::Building(id) => {
return Some(self.get_b(id));
}
ID::Car(id) => ui.primary.sim.get_draw_car(id, &ui.primary.map).unwrap().on,
ID::Pedestrian(id) => ui.primary.sim.get_draw_ped(id, &ui.primary.map).unwrap().on,
ID::PedCrowd(ref members) => {
// If the first member has vanished, just give up
ui.primary.sim.get_draw_ped(members[0], &ui.primary.map)?.on
}
ID::ExtraShape(id) => {
return Some(self.get_es(id));
}
ID::BusStop(id) => {
return Some(self.get_bs(id));
}
ID::Area(id) => {
return Some(self.get_a(id));
}
ID::Trip(_) => unreachable!(),
};
agents.populate_if_needed(on, &ui.primary.map, &ui.primary.sim, &ui.cs, prerender);
// Why might this fail? Pedestrians merge into crowds, and crowds dissipate into
// individuals
agents.get(on).into_iter().find(|r| r.get_id() == id)
}
// Unsorted, unexpanded, raw result.
pub fn get_matching_objects(&self, bounds: Bounds) -> Vec<ID> {
let mut results: Vec<ID> = Vec::new();
@ -300,14 +346,6 @@ pub struct AgentCache {
}
impl AgentCache {
pub fn has(&self, now: Time, on: Traversable) -> bool {
if Some(now) != self.time {
return false;
}
self.agents_per_on.contains_key(&on)
}
// Must call has() first.
pub fn get(&self, on: Traversable) -> Vec<&dyn Renderable> {
self.agents_per_on[&on]
.iter()
@ -315,14 +353,40 @@ impl AgentCache {
.collect()
}
pub fn put(&mut self, now: Time, on: Traversable, agents: Vec<Box<dyn Renderable>>) {
pub fn populate_if_needed(
&mut self,
on: Traversable,
map: &Map,
source: &dyn GetDrawAgents,
cs: &ColorScheme,
prerender: &Prerender,
) {
let now = source.time();
if Some(now) == self.time && self.agents_per_on.contains_key(&on) {
return;
}
let step_count = source.step_count();
let mut list: Vec<Box<dyn Renderable>> = Vec::new();
for c in source.get_draw_cars(on, map).into_iter() {
list.push(draw_vehicle(c, map, prerender, 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, cs,
)));
}
for c in crowds {
list.push(Box::new(DrawPedCrowd::new(c, map, prerender, cs)));
}
if Some(now) != self.time {
self.agents_per_on.clear();
self.time = Some(now);
}
assert!(!self.agents_per_on.contains_key(&on));
self.agents_per_on.insert(on, agents);
self.agents_per_on.insert(on, list);
}
// TODO GetDrawAgents indirection added for time traveling, but that's been removed. Maybe

View File

@ -14,14 +14,13 @@ mod turn;
use crate::helpers::{ColorScheme, ID};
use crate::options::Options;
pub use crate::render::area::DrawArea;
use crate::render::bike::DrawBike;
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, AgentColorScheme, DrawMap, InnerAgentColorScheme};
pub use crate::render::pedestrian::{DrawPedCrowd, DrawPedestrian};
use crate::render::pedestrian::{DrawPedCrowd, DrawPedestrian};
pub use crate::render::road::DrawRoad;
pub use crate::render::traffic_signal::draw_signal_phase;
pub use crate::render::turn::{DrawTurn, DrawTurnGroup};
@ -61,7 +60,7 @@ pub trait Renderable {
}
}
pub fn draw_vehicle(
fn draw_vehicle(
input: DrawCarInput,
map: &Map,
prerender: &Prerender,

View File

@ -3,8 +3,7 @@ use crate::helpers::{ColorScheme, ID};
use crate::obj_actions::PerObjectActions;
use crate::options::Options;
use crate::render::{
draw_vehicle, AgentCache, AgentColorScheme, DrawCtx, DrawMap, DrawOptions, DrawPedCrowd,
DrawPedestrian, Renderable, MIN_ZOOM_FOR_DETAIL,
AgentCache, AgentColorScheme, DrawCtx, DrawMap, DrawOptions, Renderable, MIN_ZOOM_FOR_DETAIL,
};
use abstutil::{MeasureMemory, Timer};
use ezgui::{Color, EventCtx, GfxCtx, Prerender, TextureType};
@ -349,26 +348,8 @@ impl UI {
// Expand all of the Traversables into agents, populating the cache if needed.
{
let time = source.time();
let step_count = source.step_count();
for on in &agents_on {
if !agents.has(time, *on) {
let mut list: Vec<Box<dyn Renderable>> = Vec::new();
for c in source.get_draw_cars(*on, map).into_iter() {
list.push(draw_vehicle(c, map, prerender, &self.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,
)));
}
for c in crowds {
list.push(Box::new(DrawPedCrowd::new(c, map, prerender, &self.cs)));
}
agents.put(time, *on, list);
}
agents.populate_if_needed(*on, map, source, &self.cs, prerender);
}
}