mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 16:36:02 +03:00
display when a traffic signal is in overtime
This commit is contained in:
parent
a8ee229793
commit
3f2a7d6e68
@ -157,3 +157,8 @@ Shelby and 23rd...
|
||||
- need to fix up IDs everywhere
|
||||
|
||||
- ... rest of map construction proceeds
|
||||
|
||||
## Live editing
|
||||
|
||||
Traffic signal changes can happen live, because weird changes will just look
|
||||
like brief blips of overtime. Same for stop signs, I think...
|
||||
|
@ -98,6 +98,7 @@ pub fn default_colors() -> HashMap<String, Color> {
|
||||
m.insert("sidewalk corner".to_string(), Color::grey(0.7));
|
||||
m.insert("sidewalk lines".to_string(), Color::grey(0.7));
|
||||
m.insert("signal editor panel".to_string(), Color::BLACK.alpha(0.95));
|
||||
m.insert("signal overtime timer".to_string(), Color::PINK);
|
||||
m.insert(
|
||||
"something associated with something else".to_string(),
|
||||
Color::PURPLE,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::objects::{Ctx, ID};
|
||||
use crate::plugins::{Plugin, PluginCtx};
|
||||
use crate::render::{draw_signal_cycle, draw_stop_sign, stop_sign_rendering_hints, DrawTurn};
|
||||
use ezgui::{Color, GfxCtx};
|
||||
use ezgui::{Color, GfxCtx, Text};
|
||||
use geom::{Polygon, Pt2D};
|
||||
use map_model::{IntersectionID, LaneID, TurnType};
|
||||
use piston::input::Key;
|
||||
@ -34,12 +34,14 @@ impl Plugin for TurnCyclerState {
|
||||
self.state = State::ShowIntersection(id);
|
||||
|
||||
if let Some(signal) = ctx.primary.map.maybe_get_traffic_signal(id) {
|
||||
let (cycle, _) =
|
||||
signal.current_cycle_and_remaining_time(ctx.primary.sim.time.as_time());
|
||||
ctx.hints.suppress_intersection_icon = Some(id);
|
||||
ctx.hints
|
||||
.hide_crosswalks
|
||||
.extend(cycle.get_absent_crosswalks(&ctx.primary.map));
|
||||
if !ctx.primary.sim.is_in_overtime(id) {
|
||||
let (cycle, _) =
|
||||
signal.current_cycle_and_remaining_time(ctx.primary.sim.time.as_time());
|
||||
ctx.hints
|
||||
.hide_crosswalks
|
||||
.extend(cycle.get_absent_crosswalks(&ctx.primary.map));
|
||||
}
|
||||
} else if let Some(sign) = ctx.primary.map.maybe_get_stop_sign(id) {
|
||||
stop_sign_rendering_hints(&mut ctx.hints, sign, &ctx.primary.map, ctx.cs);
|
||||
}
|
||||
@ -100,37 +102,54 @@ impl Plugin for TurnCyclerState {
|
||||
}
|
||||
State::ShowIntersection(id) => {
|
||||
if let Some(signal) = ctx.map.maybe_get_traffic_signal(id) {
|
||||
// TODO Cycle might be over-run; should depict that by asking sim layer.
|
||||
let (cycle, time_left) =
|
||||
signal.current_cycle_and_remaining_time(ctx.sim.time.as_time());
|
||||
|
||||
draw_signal_cycle(
|
||||
cycle,
|
||||
g,
|
||||
ctx.cs,
|
||||
ctx.map,
|
||||
ctx.draw_map,
|
||||
&ctx.hints.hide_crosswalks,
|
||||
);
|
||||
|
||||
// Draw a little timer box in the top-left corner of the screen.
|
||||
{
|
||||
if ctx.sim.is_in_overtime(id) {
|
||||
let old_ctx = g.fork_screenspace();
|
||||
let width = 50.0;
|
||||
let height = 100.0;
|
||||
g.draw_polygon(
|
||||
ctx.cs.get_def("timer foreground", Color::RED),
|
||||
ctx.cs.get_def("signal overtime timer", Color::PINK),
|
||||
&Polygon::rectangle_topleft(Pt2D::new(10.0, 10.0), width, height),
|
||||
);
|
||||
g.draw_polygon(
|
||||
ctx.cs.get_def("timer background", Color::BLACK),
|
||||
&Polygon::rectangle_topleft(
|
||||
Pt2D::new(10.0, 10.0),
|
||||
width,
|
||||
(time_left / cycle.duration).value_unsafe * height,
|
||||
),
|
||||
// TODO We can't use draw_text_at, because canvas doesn't know about forked
|
||||
// contexts.
|
||||
ctx.canvas.draw_text_at_screenspace_topleft(
|
||||
g,
|
||||
Text::from_line("Overtime!".to_string()),
|
||||
(10.0 + width / 2.0, 10.0 + height / 2.0),
|
||||
);
|
||||
g.unfork(old_ctx);
|
||||
} else {
|
||||
let (cycle, time_left) =
|
||||
signal.current_cycle_and_remaining_time(ctx.sim.time.as_time());
|
||||
|
||||
draw_signal_cycle(
|
||||
cycle,
|
||||
g,
|
||||
ctx.cs,
|
||||
ctx.map,
|
||||
ctx.draw_map,
|
||||
&ctx.hints.hide_crosswalks,
|
||||
);
|
||||
|
||||
// Draw a little timer box in the top-left corner of the screen.
|
||||
{
|
||||
let old_ctx = g.fork_screenspace();
|
||||
let width = 50.0;
|
||||
let height = 100.0;
|
||||
g.draw_polygon(
|
||||
ctx.cs.get_def("timer foreground", Color::RED),
|
||||
&Polygon::rectangle_topleft(Pt2D::new(10.0, 10.0), width, height),
|
||||
);
|
||||
g.draw_polygon(
|
||||
ctx.cs.get_def("timer background", Color::BLACK),
|
||||
&Polygon::rectangle_topleft(
|
||||
Pt2D::new(10.0, 10.0),
|
||||
width,
|
||||
(time_left / cycle.duration).value_unsafe * height,
|
||||
),
|
||||
);
|
||||
g.unfork(old_ctx);
|
||||
}
|
||||
}
|
||||
} else if let Some(sign) = ctx.map.maybe_get_stop_sign(id) {
|
||||
draw_stop_sign(sign, g, ctx.cs, ctx.map);
|
||||
|
@ -26,6 +26,7 @@ impl Color {
|
||||
pub const CYAN: Color = Color([0.0, 1.0, 1.0, 1.0]);
|
||||
pub const YELLOW: Color = Color([1.0, 1.0, 0.0, 1.0]);
|
||||
pub const PURPLE: Color = Color([0.5, 0.0, 0.5, 1.0]);
|
||||
pub const PINK: Color = Color([1.0, 0.41, 0.71, 1.0]);
|
||||
|
||||
// TODO should assert stuff about the inputs
|
||||
|
||||
|
@ -53,6 +53,8 @@ impl<'a> GfxCtx<'a> {
|
||||
}
|
||||
|
||||
// Up to the caller to call unfork()!
|
||||
// TODO Canvas doesn't understand this change, so things like text drawing that use
|
||||
// map_to_screen will just be confusing.
|
||||
pub fn fork(&mut self, top_left: Pt2D, zoom: f64) -> graphics::Context {
|
||||
mem::replace(
|
||||
&mut self.ctx,
|
||||
|
@ -166,6 +166,14 @@ impl IntersectionSimState {
|
||||
IntersectionPolicy::Border => HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_in_overtime(&self, id: IntersectionID) -> bool {
|
||||
match self.intersections[id.0] {
|
||||
IntersectionPolicy::StopSign(_) => unreachable!(),
|
||||
IntersectionPolicy::TrafficSignal(ref p) => p.overtime,
|
||||
IntersectionPolicy::Border => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use an enum instead of traits so that serialization works. I couldn't figure out erased_serde.
|
||||
@ -307,6 +315,7 @@ struct TrafficSignal {
|
||||
id: IntersectionID,
|
||||
accepted: BTreeSet<Request>,
|
||||
requests: BTreeSet<Request>,
|
||||
overtime: bool,
|
||||
debug: bool,
|
||||
}
|
||||
|
||||
@ -316,6 +325,7 @@ impl TrafficSignal {
|
||||
id,
|
||||
accepted: BTreeSet::new(),
|
||||
requests: BTreeSet::new(),
|
||||
overtime: false,
|
||||
debug: false,
|
||||
}
|
||||
}
|
||||
@ -334,9 +344,11 @@ impl TrafficSignal {
|
||||
req.agent, req.turn
|
||||
);
|
||||
}
|
||||
self.overtime = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.overtime = false;
|
||||
|
||||
let priority_requests: BTreeSet<TurnID> = self
|
||||
.requests
|
||||
|
@ -415,6 +415,10 @@ impl Sim {
|
||||
self.intersection_state.get_accepted_agents(id)
|
||||
}
|
||||
|
||||
pub fn is_in_overtime(&self, id: IntersectionID) -> bool {
|
||||
self.intersection_state.is_in_overtime(id)
|
||||
}
|
||||
|
||||
pub fn get_stats(&self) -> &SimStats {
|
||||
&self.stats
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user