mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-29 01:13:53 +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::app::App;
|
||||||
use crate::helpers::ID;
|
use crate::helpers::{ColorScheme, ID};
|
||||||
use crate::info::{header_btns, make_table, make_tabs, Details, Tab};
|
use crate::info::{header_btns, make_table, make_tabs, Details, Tab};
|
||||||
|
use crate::render::DrawPedestrian;
|
||||||
use ezgui::{Btn, EventCtx, Line, Text, TextExt, Widget};
|
use ezgui::{Btn, EventCtx, Line, Text, TextExt, Widget};
|
||||||
use geom::Time;
|
use geom::{Angle, Time};
|
||||||
use map_model::BuildingID;
|
use map_model::{Building, BuildingID, LaneID, Traversable, SIDEWALK_THICKNESS};
|
||||||
use sim::{TripMode, TripResult};
|
use sim::{DrawPedestrianInput, PedestrianID, TripMode, TripResult};
|
||||||
|
|
||||||
pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID) -> Vec<Widget> {
|
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));
|
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
|
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::intersection::{calculate_corners, DrawIntersection};
|
||||||
pub use crate::render::lane::DrawLane;
|
pub use crate::render::lane::DrawLane;
|
||||||
pub use crate::render::map::{AgentCache, AgentColorScheme, DrawMap};
|
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::road::DrawRoad;
|
||||||
pub use crate::render::traffic_signal::{draw_signal_phase, make_signal_diagram};
|
pub use crate::render::traffic_signal::{draw_signal_phase, make_signal_diagram};
|
||||||
pub use crate::render::turn::{DrawTurn, DrawTurnGroup};
|
pub use crate::render::turn::{DrawTurn, DrawTurnGroup};
|
||||||
|
@ -22,6 +22,40 @@ impl DrawPedestrian {
|
|||||||
prerender: &Prerender,
|
prerender: &Prerender,
|
||||||
cs: &ColorScheme,
|
cs: &ColorScheme,
|
||||||
) -> DrawPedestrian {
|
) -> 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:
|
// TODO Slight issues with rendering small pedestrians:
|
||||||
// - route visualization is thick
|
// - route visualization is thick
|
||||||
// - there are little skips when making turns
|
// - 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 radius = SIDEWALK_THICKNESS / 4.0; // TODO make const after const fn is better
|
||||||
let body_circle = Circle::new(input.pos, radius);
|
let body_circle = Circle::new(input.pos, radius);
|
||||||
|
|
||||||
let mut draw_default = GeomBatch::new();
|
|
||||||
|
|
||||||
let foot_radius = 0.2 * radius;
|
let foot_radius = 0.2 * radius;
|
||||||
let hand_radius = 0.2 * radius;
|
let hand_radius = 0.2 * radius;
|
||||||
let left_foot_angle = 30.0;
|
let left_foot_angle = 30.0;
|
||||||
@ -68,13 +100,13 @@ impl DrawPedestrian {
|
|||||||
let jitter = input.id.0 % 2 == 0;
|
let jitter = input.id.0 % 2 == 0;
|
||||||
let remainder = step_count % 6;
|
let remainder = step_count % 6;
|
||||||
if input.waiting_for_turn.is_some() || input.waiting_for_bus {
|
if input.waiting_for_turn.is_some() || input.waiting_for_bus {
|
||||||
draw_default.push(foot_color, left_foot.to_polygon());
|
batch.push(foot_color, left_foot.to_polygon());
|
||||||
draw_default.push(foot_color, right_foot.to_polygon());
|
batch.push(foot_color, right_foot.to_polygon());
|
||||||
draw_default.push(hand_color, left_hand.to_polygon());
|
batch.push(hand_color, left_hand.to_polygon());
|
||||||
draw_default.push(hand_color, right_hand.to_polygon());
|
batch.push(hand_color, right_hand.to_polygon());
|
||||||
} else if jitter == (remainder < 3) {
|
} else if jitter == (remainder < 3) {
|
||||||
draw_default.push(foot_color, left_foot.to_polygon());
|
batch.push(foot_color, left_foot.to_polygon());
|
||||||
draw_default.push(
|
batch.push(
|
||||||
foot_color,
|
foot_color,
|
||||||
Circle::new(
|
Circle::new(
|
||||||
input
|
input
|
||||||
@ -85,8 +117,8 @@ impl DrawPedestrian {
|
|||||||
.to_polygon(),
|
.to_polygon(),
|
||||||
);
|
);
|
||||||
|
|
||||||
draw_default.push(hand_color, right_hand.to_polygon());
|
batch.push(hand_color, right_hand.to_polygon());
|
||||||
draw_default.push(
|
batch.push(
|
||||||
hand_color,
|
hand_color,
|
||||||
Circle::new(
|
Circle::new(
|
||||||
input
|
input
|
||||||
@ -97,8 +129,8 @@ impl DrawPedestrian {
|
|||||||
.to_polygon(),
|
.to_polygon(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
draw_default.push(foot_color, right_foot.to_polygon());
|
batch.push(foot_color, right_foot.to_polygon());
|
||||||
draw_default.push(
|
batch.push(
|
||||||
foot_color,
|
foot_color,
|
||||||
Circle::new(
|
Circle::new(
|
||||||
input
|
input
|
||||||
@ -109,8 +141,8 @@ impl DrawPedestrian {
|
|||||||
.to_polygon(),
|
.to_polygon(),
|
||||||
);
|
);
|
||||||
|
|
||||||
draw_default.push(hand_color, left_hand.to_polygon());
|
batch.push(hand_color, left_hand.to_polygon());
|
||||||
draw_default.push(
|
batch.push(
|
||||||
hand_color,
|
hand_color,
|
||||||
Circle::new(
|
Circle::new(
|
||||||
input
|
input
|
||||||
@ -123,32 +155,11 @@ impl DrawPedestrian {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let head_circle = Circle::new(input.pos, 0.5 * radius);
|
let head_circle = Circle::new(input.pos, 0.5 * radius);
|
||||||
draw_default.push(zoomed_color_ped(&input, cs), body_circle.to_polygon());
|
batch.push(zoomed_color_ped(&input, cs), body_circle.to_polygon());
|
||||||
draw_default.push(
|
batch.push(
|
||||||
cs.get_def("pedestrian head", Color::rgb(139, 69, 19)),
|
cs.get_def("pedestrian head", Color::rgb(139, 69, 19)),
|
||||||
head_circle.to_polygon(),
|
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