mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 16:36:02 +03:00
draw people inside buildings!
This commit is contained in:
parent
e2cc9dbb55
commit
555b793910
@ -1,10 +1,11 @@
|
||||
use crate::app::App;
|
||||
use crate::helpers::ID;
|
||||
use crate::helpers::{ColorScheme, ID};
|
||||
use crate::info::{header_btns, make_table, make_tabs, Details, Tab};
|
||||
use crate::render::DrawPedestrian;
|
||||
use ezgui::{Btn, EventCtx, Line, Text, TextExt, Widget};
|
||||
use geom::Time;
|
||||
use map_model::BuildingID;
|
||||
use sim::{TripMode, TripResult};
|
||||
use geom::{Angle, Time};
|
||||
use map_model::{Building, BuildingID, LaneID, Traversable, SIDEWALK_THICKNESS};
|
||||
use sim::{DrawPedestrianInput, PedestrianID, TripMode, TripResult};
|
||||
|
||||
pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID) -> Vec<Widget> {
|
||||
let mut rows = header(ctx, app, details, id, Tab::BldgInfo(id));
|
||||
@ -165,5 +166,58 @@ fn header(
|
||||
);
|
||||
}
|
||||
|
||||
draw_occupants(
|
||||
details,
|
||||
&app.cs,
|
||||
app.primary.map.get_b(id),
|
||||
app.primary.sim.bldg_to_people(id).len(),
|
||||
);
|
||||
|
||||
rows
|
||||
}
|
||||
|
||||
fn draw_occupants(details: &mut Details, cs: &ColorScheme, bldg: &Building, num_ppl: usize) {
|
||||
// TODO Lots of fun ideas here. Have a deterministic simulation based on building ID and time
|
||||
// to have people "realistically" move around. Draw little floor plans.
|
||||
|
||||
let num_rows_cols = (num_ppl as f64).sqrt().ceil() as usize;
|
||||
|
||||
let ped_len = SIDEWALK_THICKNESS.inner_meters() / 2.0;
|
||||
let separation = ped_len * 1.5;
|
||||
|
||||
let total_width_height = (num_rows_cols as f64) * (ped_len + separation);
|
||||
let top_left = bldg
|
||||
.label_center
|
||||
.offset(-total_width_height / 2.0, -total_width_height / 2.0);
|
||||
|
||||
// TODO Current thing is inefficient and can easily wind up outside the building.
|
||||
|
||||
let mut cnt = 0;
|
||||
'OUTER: for x in 0..num_rows_cols {
|
||||
for y in 0..num_rows_cols {
|
||||
DrawPedestrian::geometry(
|
||||
&mut details.zoomed,
|
||||
cs,
|
||||
&DrawPedestrianInput {
|
||||
id: PedestrianID(cnt),
|
||||
pos: top_left.offset(
|
||||
(x as f64) * (ped_len + separation),
|
||||
(y as f64) * (ped_len + separation),
|
||||
),
|
||||
facing: Angle::new_degs(90.0),
|
||||
waiting_for_turn: None,
|
||||
preparing_bike: false,
|
||||
// Both hands and feet!
|
||||
waiting_for_bus: true,
|
||||
on: Traversable::Lane(LaneID(0)),
|
||||
},
|
||||
0,
|
||||
);
|
||||
|
||||
cnt += 1;
|
||||
if cnt == num_ppl {
|
||||
break 'OUTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ 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};
|
||||
use crate::render::pedestrian::{DrawPedCrowd, DrawPedestrian};
|
||||
pub use crate::render::pedestrian::{DrawPedCrowd, DrawPedestrian};
|
||||
pub use crate::render::road::DrawRoad;
|
||||
pub use crate::render::traffic_signal::{draw_signal_phase, make_signal_diagram};
|
||||
pub use crate::render::turn::{DrawTurn, DrawTurnGroup};
|
||||
|
@ -22,6 +22,40 @@ impl DrawPedestrian {
|
||||
prerender: &Prerender,
|
||||
cs: &ColorScheme,
|
||||
) -> DrawPedestrian {
|
||||
let mut draw_default = GeomBatch::new();
|
||||
DrawPedestrian::geometry(&mut draw_default, cs, &input, step_count);
|
||||
|
||||
let radius = SIDEWALK_THICKNESS / 4.0; // TODO make const after const fn is better
|
||||
let body_circle = Circle::new(input.pos, radius);
|
||||
|
||||
if let Some(t) = input.waiting_for_turn {
|
||||
// A silly idea for peds... use hands to point at their turn?
|
||||
let angle = map.get_t(t).angle();
|
||||
draw_default.push(
|
||||
cs.get("turn arrow"),
|
||||
PolyLine::new(vec![
|
||||
input.pos.project_away(radius / 2.0, angle.opposite()),
|
||||
input.pos.project_away(radius / 2.0, angle),
|
||||
])
|
||||
.make_arrow(Distance::meters(0.15))
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
DrawPedestrian {
|
||||
id: input.id,
|
||||
body_circle,
|
||||
zorder: input.on.get_zorder(map),
|
||||
draw_default: prerender.upload(draw_default),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn geometry(
|
||||
batch: &mut GeomBatch,
|
||||
cs: &ColorScheme,
|
||||
input: &DrawPedestrianInput,
|
||||
step_count: usize,
|
||||
) {
|
||||
// TODO Slight issues with rendering small pedestrians:
|
||||
// - route visualization is thick
|
||||
// - there are little skips when making turns
|
||||
@ -29,8 +63,6 @@ impl DrawPedestrian {
|
||||
let radius = SIDEWALK_THICKNESS / 4.0; // TODO make const after const fn is better
|
||||
let body_circle = Circle::new(input.pos, radius);
|
||||
|
||||
let mut draw_default = GeomBatch::new();
|
||||
|
||||
let foot_radius = 0.2 * radius;
|
||||
let hand_radius = 0.2 * radius;
|
||||
let left_foot_angle = 30.0;
|
||||
@ -68,13 +100,13 @@ impl DrawPedestrian {
|
||||
let jitter = input.id.0 % 2 == 0;
|
||||
let remainder = step_count % 6;
|
||||
if input.waiting_for_turn.is_some() || input.waiting_for_bus {
|
||||
draw_default.push(foot_color, left_foot.to_polygon());
|
||||
draw_default.push(foot_color, right_foot.to_polygon());
|
||||
draw_default.push(hand_color, left_hand.to_polygon());
|
||||
draw_default.push(hand_color, right_hand.to_polygon());
|
||||
batch.push(foot_color, left_foot.to_polygon());
|
||||
batch.push(foot_color, right_foot.to_polygon());
|
||||
batch.push(hand_color, left_hand.to_polygon());
|
||||
batch.push(hand_color, right_hand.to_polygon());
|
||||
} else if jitter == (remainder < 3) {
|
||||
draw_default.push(foot_color, left_foot.to_polygon());
|
||||
draw_default.push(
|
||||
batch.push(foot_color, left_foot.to_polygon());
|
||||
batch.push(
|
||||
foot_color,
|
||||
Circle::new(
|
||||
input
|
||||
@ -85,8 +117,8 @@ impl DrawPedestrian {
|
||||
.to_polygon(),
|
||||
);
|
||||
|
||||
draw_default.push(hand_color, right_hand.to_polygon());
|
||||
draw_default.push(
|
||||
batch.push(hand_color, right_hand.to_polygon());
|
||||
batch.push(
|
||||
hand_color,
|
||||
Circle::new(
|
||||
input
|
||||
@ -97,8 +129,8 @@ impl DrawPedestrian {
|
||||
.to_polygon(),
|
||||
);
|
||||
} else {
|
||||
draw_default.push(foot_color, right_foot.to_polygon());
|
||||
draw_default.push(
|
||||
batch.push(foot_color, right_foot.to_polygon());
|
||||
batch.push(
|
||||
foot_color,
|
||||
Circle::new(
|
||||
input
|
||||
@ -109,8 +141,8 @@ impl DrawPedestrian {
|
||||
.to_polygon(),
|
||||
);
|
||||
|
||||
draw_default.push(hand_color, left_hand.to_polygon());
|
||||
draw_default.push(
|
||||
batch.push(hand_color, left_hand.to_polygon());
|
||||
batch.push(
|
||||
hand_color,
|
||||
Circle::new(
|
||||
input
|
||||
@ -123,32 +155,11 @@ impl DrawPedestrian {
|
||||
};
|
||||
|
||||
let head_circle = Circle::new(input.pos, 0.5 * radius);
|
||||
draw_default.push(zoomed_color_ped(&input, cs), body_circle.to_polygon());
|
||||
draw_default.push(
|
||||
batch.push(zoomed_color_ped(&input, cs), body_circle.to_polygon());
|
||||
batch.push(
|
||||
cs.get_def("pedestrian head", Color::rgb(139, 69, 19)),
|
||||
head_circle.to_polygon(),
|
||||
);
|
||||
|
||||
if let Some(t) = input.waiting_for_turn {
|
||||
// A silly idea for peds... use hands to point at their turn?
|
||||
let angle = map.get_t(t).angle();
|
||||
draw_default.push(
|
||||
cs.get("turn arrow"),
|
||||
PolyLine::new(vec![
|
||||
input.pos.project_away(radius / 2.0, angle.opposite()),
|
||||
input.pos.project_away(radius / 2.0, angle),
|
||||
])
|
||||
.make_arrow(Distance::meters(0.15))
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
DrawPedestrian {
|
||||
id: input.id,
|
||||
body_circle,
|
||||
zorder: input.on.get_zorder(map),
|
||||
draw_default: prerender.upload(draw_default),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user