mirror of
https://github.com/a-b-street/abstreet.git
synced 2025-01-03 12:03:30 +03:00
when an info panel is open, keep an outline on the object. dont quite
handle peds <-> crowds
This commit is contained in:
parent
ffdde86fc6
commit
6452953370
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user