diff --git a/game/src/info/building.rs b/game/src/info/building.rs index af6749cc39..1ddf32d503 100644 --- a/game/src/info/building.rs +++ b/game/src/info/building.rs @@ -1,6 +1,6 @@ use crate::app::App; use crate::info::{header_btns, make_table, make_tabs, Details, Tab}; -use crate::render::{dashed_lines, DrawPedestrian}; +use crate::render::DrawPedestrian; use ezgui::{Btn, Color, EventCtx, Line, Text, TextExt, Widget}; use geom::{Angle, Circle, Distance, Speed, Time}; use map_model::{BuildingID, LaneID, Traversable, SIDEWALK_THICKNESS}; @@ -68,8 +68,7 @@ pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID .push(color, pl.make_polygons(Distance::meters(10.0))); details.zoomed.extend( color, - dashed_lines( - &pl, + pl.dashed_lines( Distance::meters(0.75), Distance::meters(1.0), Distance::meters(0.4), diff --git a/game/src/info/trip.rs b/game/src/info/trip.rs index 10b1f9cec9..721fd301ad 100644 --- a/game/src/info/trip.rs +++ b/game/src/info/trip.rs @@ -1,7 +1,6 @@ use crate::app::App; use crate::helpers::ID; use crate::info::{make_table, Details, Tab}; -use crate::render::dashed_lines; use ezgui::{ Btn, Color, EventCtx, GeomBatch, Line, LinePlot, PlotOptions, RewriteColor, Series, Text, TextExt, Widget, @@ -488,8 +487,7 @@ fn make_timeline( .push(color, trace.make_polygons(Distance::meters(10.0))); details.zoomed.extend( color, - dashed_lines( - &trace, + trace.dashed_lines( Distance::meters(0.75), Distance::meters(1.0), Distance::meters(0.4), diff --git a/game/src/render/lane.rs b/game/src/render/lane.rs index 090bbd81d1..0f358d1471 100644 --- a/game/src/render/lane.rs +++ b/game/src/render/lane.rs @@ -1,7 +1,7 @@ use crate::app::App; use crate::colors::ColorScheme; use crate::helpers::ID; -use crate::render::{dashed_lines, DrawOptions, Renderable, OUTLINE_THICKNESS}; +use crate::render::{DrawOptions, Renderable, OUTLINE_THICKNESS}; use abstutil::Timer; use ezgui::{Drawable, FancyColor, GeomBatch, GfxCtx, Prerender, RewriteColor}; use geom::{Angle, Distance, Line, PolyLine, Polygon, Pt2D}; @@ -257,8 +257,7 @@ fn calculate_driving_lines( let lane_edge_pts = map .left_shift(lane.lane_center_pts.clone(), lane.width / 2.0) .get(timer); - dashed_lines( - &lane_edge_pts, + lane_edge_pts.dashed_lines( Distance::meters(0.25), Distance::meters(1.0), Distance::meters(1.5), diff --git a/game/src/render/mod.rs b/game/src/render/mod.rs index daefc485d4..02304c76f9 100644 --- a/game/src/render/mod.rs +++ b/game/src/render/mod.rs @@ -24,9 +24,9 @@ pub use crate::render::map::{AgentCache, AgentColorScheme, DrawMap}; 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}; +pub use crate::render::turn::DrawTurnGroup; use ezgui::{GfxCtx, Prerender}; -use geom::{Distance, PolyLine, Polygon, Pt2D, EPSILON_DIST}; +use geom::{Distance, Polygon, Pt2D}; use map_model::{IntersectionID, Map}; use sim::{DrawCarInput, VehicleType}; @@ -72,20 +72,6 @@ fn draw_vehicle( } } -pub fn dashed_lines( - pl: &PolyLine, - width: Distance, - dash_len: Distance, - dash_separation: Distance, -) -> Vec { - if pl.length() < dash_separation * 2.0 + EPSILON_DIST { - return vec![pl.make_polygons(width)]; - } - // Don't draw the dashes too close to the ends. - pl.exact_slice(dash_separation, pl.length() - dash_separation) - .dashed_polygons(width, dash_len, dash_separation) -} - // TODO Borrow, don't clone, and fix up lots of places storing indirect things to populate // DrawOptions. #[derive(Clone)] diff --git a/game/src/render/road.rs b/game/src/render/road.rs index 1e4e43a813..6a03bc1b94 100644 --- a/game/src/render/road.rs +++ b/game/src/render/road.rs @@ -1,7 +1,7 @@ use crate::app::App; use crate::colors::ColorScheme; use crate::helpers::ID; -use crate::render::{dashed_lines, DrawOptions, Renderable}; +use crate::render::{DrawOptions, Renderable}; use ezgui::{Drawable, GeomBatch, GfxCtx, Line, Prerender, RewriteColor, Text}; use geom::{Angle, Distance, Polygon, Pt2D}; use map_model::{LaneType, Map, Road, RoadID}; @@ -31,7 +31,7 @@ impl DrawRoad { { draw.extend( cs.road_center_line, - dashed_lines(¢er, width, Distance::meters(2.0), Distance::meters(1.0)), + center.dashed_lines(width, Distance::meters(2.0), Distance::meters(1.0)), ); } diff --git a/game/src/render/turn.rs b/game/src/render/turn.rs index 3d681cda33..67c2fbc264 100644 --- a/game/src/render/turn.rs +++ b/game/src/render/turn.rs @@ -1,51 +1,9 @@ -use crate::render::BIG_ARROW_THICKNESS; -use ezgui::{Color, GeomBatch, GfxCtx}; -use geom::{Distance, Line, PolyLine, Polygon}; -use map_model::{IntersectionID, LaneID, Map, Turn, TurnGroupID}; +use geom::{Distance, PolyLine, Polygon}; +use map_model::{IntersectionID, LaneID, Map, TurnGroupID}; use std::collections::{HashMap, HashSet}; const TURN_ICON_ARROW_LENGTH: Distance = Distance::const_meters(1.5); -pub struct DrawTurn {} - -impl DrawTurn { - pub fn draw_full(t: &Turn, g: &mut GfxCtx, color: Color) { - g.draw_polygon( - color, - &t.geom - .make_arrow(BIG_ARROW_THICKNESS) - .expect(format!("draw_full {}", t.id)), - ); - } - - // TODO make a polyline.dashed or something - // TODO get rid of all these weird DrawTurn things generally - pub fn draw_dashed(turn: &Turn, batch: &mut GeomBatch, color: Color) { - let dash_len = Distance::meters(1.0); - batch.extend( - color, - turn.geom - .dashed_polygons(BIG_ARROW_THICKNESS, dash_len, Distance::meters(0.5)), - ); - // And a cap on the arrow. In case the last line is long, trim it to be the dash - // length. - let last_line = turn.geom.last_line(); - let last_len = last_line.length(); - let arrow_line = if last_len <= dash_len { - last_line - } else { - Line::new(last_line.dist_along(last_len - dash_len), last_line.pt2()) - }; - batch.push( - color, - arrow_line - .to_polyline() - .make_arrow(BIG_ARROW_THICKNESS) - .unwrap(), - ); - } -} - pub struct DrawTurnGroup { pub id: TurnGroupID, pub block: Polygon, diff --git a/game/src/sandbox/misc_tools.rs b/game/src/sandbox/misc_tools.rs index 9f4d270193..b232169ba1 100644 --- a/game/src/sandbox/misc_tools.rs +++ b/game/src/sandbox/misc_tools.rs @@ -1,7 +1,7 @@ use crate::app::{App, ShowEverything}; use crate::common::ColorLegend; use crate::game::{DrawBaselayer, State, Transition}; -use crate::render::{dashed_lines, draw_signal_phase, make_signal_diagram, DrawOptions, DrawTurn}; +use crate::render::{draw_signal_phase, make_signal_diagram, DrawOptions, BIG_ARROW_THICKNESS}; use ezgui::{ hotkey, Btn, Color, Composite, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Text, VerticalAlignment, Widget, @@ -39,8 +39,7 @@ impl RoutePreview { let mut batch = GeomBatch::new(); batch.extend( app.cs.route, - dashed_lines( - &trace, + trace.dashed_lines( Distance::meters(0.75), Distance::meters(1.0), Distance::meters(0.4), @@ -208,7 +207,10 @@ impl State for TurnExplorer { if self.idx == 0 { for turn in &app.primary.map.get_turns_from_lane(self.l) { - DrawTurn::draw_full(turn, g, color_turn_type(turn.turn_type).alpha(0.5)); + g.draw_polygon( + color_turn_type(turn.turn_type).alpha(0.5), + &turn.geom.make_arrow(BIG_ARROW_THICKNESS).unwrap(), + ); } } else { let current = &app.primary.map.get_turns_from_lane(self.l)[self.idx - 1]; @@ -216,12 +218,21 @@ impl State for TurnExplorer { let mut batch = GeomBatch::new(); for t in app.primary.map.get_turns_in_intersection(current.id.parent) { if current.conflicts_with(t) { - DrawTurn::draw_dashed(t, &mut batch, CONFLICTING_TURN); + batch.extend( + CONFLICTING_TURN, + t.geom.dashed_arrow( + BIG_ARROW_THICKNESS, + Distance::meters(1.0), + Distance::meters(0.5), + ), + ); } } + batch.push( + CURRENT_TURN, + current.geom.make_arrow(BIG_ARROW_THICKNESS).unwrap(), + ); batch.draw(g); - - DrawTurn::draw_full(current, g, CURRENT_TURN); } self.composite.draw(g); diff --git a/geom/src/polyline.rs b/geom/src/polyline.rs index 8e69c06688..d754a0cf60 100644 --- a/geom/src/polyline.rs +++ b/geom/src/polyline.rs @@ -451,7 +451,7 @@ impl PolyLine { Polygon::precomputed(points, indices) } - pub fn dashed_polygons( + pub fn exact_dashed_polygons( &self, width: Distance, dash_len: Distance, @@ -477,6 +477,20 @@ impl PolyLine { polygons } + // Don't draw the dashes too close to the ends. + pub fn dashed_lines( + &self, + width: Distance, + dash_len: Distance, + dash_separation: Distance, + ) -> Vec { + if self.length() < dash_separation * 2.0 + EPSILON_DIST { + return vec![self.make_polygons(width)]; + } + self.exact_slice(dash_separation, self.length() - dash_separation) + .exact_dashed_polygons(width, dash_len, dash_separation) + } + pub fn make_arrow(&self, thickness: Distance) -> Warn { let head_size = thickness * 2.0; let triangle_height = head_size / 2.0_f64.sqrt(); @@ -544,6 +558,26 @@ impl PolyLine { } } + pub fn dashed_arrow( + &self, + width: Distance, + dash_len: Distance, + dash_separation: Distance, + ) -> Vec { + let mut polygons = self.exact_dashed_polygons(width, dash_len, dash_separation); + // And a cap on the arrow. In case the last line is long, trim it to be the dash + // length. + let last_line = self.last_line(); + let last_len = last_line.length(); + let arrow_line = if last_len <= dash_len { + last_line + } else { + Line::new(last_line.dist_along(last_len - dash_len), last_line.pt2()) + }; + polygons.push(arrow_line.to_polyline().make_arrow(width).unwrap()); + polygons + } + // Also return the angle of the line where the hit was found // TODO Also return distance along self of the hit pub fn intersection(&self, other: &PolyLine) -> Option<(Pt2D, Angle)> {