diff --git a/ltn/src/browse.rs b/ltn/src/browse.rs index 53f5b668c6..682ab30e13 100644 --- a/ltn/src/browse.rs +++ b/ltn/src/browse.rs @@ -11,13 +11,13 @@ use widgetry::{ }; use super::{Neighborhood, NeighborhoodID, Partitioning}; -use crate::{App, ModalFilters, Transition}; +use crate::{App, ModalFilters, Toggle3Zoomed, Transition}; pub struct BrowseNeighborhoods { panel: Panel, world: World, labels: DrawRoadLabels, - draw_all_filters: ToggleZoomed, + draw_all_filters: Toggle3Zoomed, draw_boundary_roads: ToggleZoomed, } @@ -173,10 +173,10 @@ impl State for BrowseNeighborhoods { crate::draw_with_layering(g, app, |g| self.world.draw(g)); self.panel.draw(g); - self.draw_all_filters.draw(g); if self.panel.is_checked("highlight boundary roads") { self.draw_boundary_roads.draw(g); } + self.draw_all_filters.draw(g); if g.canvas.is_unzoomed() { self.labels.draw(g, app); } @@ -249,7 +249,7 @@ fn draw_boundary_roads(ctx: &EventCtx, app: &App) -> ToggleZoomed { let road = app.map.get_r(r); batch .unzoomed - .push(Color::RED.alpha(0.8), road.get_thick_polygon()); + .push(Color::RED.alpha(0.6), road.get_thick_polygon()); batch .zoomed .push(Color::RED.alpha(0.5), road.get_thick_polygon()); @@ -261,7 +261,7 @@ fn draw_boundary_roads(ctx: &EventCtx, app: &App) -> ToggleZoomed { seen_borders.insert(i); batch .unzoomed - .push(Color::RED.alpha(0.8), app.map.get_i(i).polygon.clone()); + .push(Color::RED.alpha(0.6), app.map.get_i(i).polygon.clone()); batch .zoomed .push(Color::RED.alpha(0.5), app.map.get_i(i).polygon.clone()); diff --git a/ltn/src/filters.rs b/ltn/src/filters.rs index 7e266480b5..c0aea13ca1 100644 --- a/ltn/src/filters.rs +++ b/ltn/src/filters.rs @@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize}; use geom::{Circle, Distance, Line}; use map_model::{IntersectionID, Map, RoadID, RoutingParams, TurnID}; -use widgetry::mapspace::ToggleZoomed; -use widgetry::{Color, EventCtx, GeomBatch}; +use widgetry::mapspace::{DrawUnzoomedShapes, ToggleZoomed}; +use widgetry::{Color, EventCtx, GeomBatch, GfxCtx}; use super::Neighborhood; use crate::App; @@ -88,8 +88,10 @@ impl ModalFilters { ctx: &EventCtx, map: &Map, only_neighborhood: Option<&Neighborhood>, - ) -> ToggleZoomed { + ) -> Toggle3Zoomed { let mut batch = ToggleZoomed::builder(); + let mut low_zoom = DrawUnzoomedShapes::builder(); + for (r, dist) in &self.roads { if only_neighborhood .map(|n| !n.orig_perimeter.interior.contains(r)) @@ -102,6 +104,11 @@ impl ModalFilters { if let Ok((pt, angle)) = road.center_pts.dist_along(*dist) { let road_width = road.get_width(); + // TODO DrawUnzoomedShapes can do lines, but they don't stretch as the radius does, + // so it looks weird + low_zoom.add_circle(pt, Distance::meters(8.0), Color::RED); + low_zoom.add_circle(pt, Distance::meters(6.0), Color::WHITE); + batch .unzoomed .push(Color::RED, Circle::new(pt, road_width).to_polygon()); @@ -134,6 +141,13 @@ impl ModalFilters { } let line = filter.geometry(map); + + // It's really hard to see a tiny squished line thickened, so use the same circle + // symbology at really low zooms + let pt = line.middle().unwrap(); + low_zoom.add_circle(pt, Distance::meters(8.0), Color::RED); + low_zoom.add_circle(pt, Distance::meters(6.0), Color::WHITE); + batch .unzoomed .push(Color::RED, line.make_polygons(Distance::meters(3.0))); @@ -144,7 +158,7 @@ impl ModalFilters { line.percent_slice(0.3, 0.7).unwrap_or(line), ); } - batch.build(ctx) + Toggle3Zoomed::new(batch.build(ctx), low_zoom.build()) } } @@ -250,3 +264,27 @@ fn draw_zoomed_planters(ctx: &EventCtx, batch: &mut GeomBatch, line: Line) { .rotate(line.angle()), ); } + +/// Depending on the canvas zoom level, draws one of 3 things. +pub struct Toggle3Zoomed { + draw: ToggleZoomed, + unzoomed: DrawUnzoomedShapes, +} + +impl Toggle3Zoomed { + fn new(draw: ToggleZoomed, unzoomed: DrawUnzoomedShapes) -> Self { + Self { draw, unzoomed } + } + + pub fn empty(ctx: &EventCtx) -> Self { + Self::new(ToggleZoomed::empty(ctx), DrawUnzoomedShapes::empty()) + } + + pub fn draw(&self, g: &mut GfxCtx) { + if g.canvas.cam_zoom < 1.0 { + self.unzoomed.draw(g); + } else { + self.draw.draw(g); + } + } +} diff --git a/ltn/src/impact/ui.rs b/ltn/src/impact/ui.rs index 07a4313cfc..4088ee64cf 100644 --- a/ltn/src/impact/ui.rs +++ b/ltn/src/impact/ui.rs @@ -3,21 +3,20 @@ use std::collections::BTreeSet; use map_gui::load::FileLoader; use map_gui::tools::{checkbox_per_mode, PopupMsg}; use synthpop::{Scenario, TripMode}; -use widgetry::mapspace::ToggleZoomed; use widgetry::{ Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line, Panel, SimpleState, Slider, State, Text, TextExt, Toggle, VerticalAlignment, Widget, }; use super::{end_of_day, Filters, Impact}; -use crate::{App, BrowseNeighborhoods, Transition}; +use crate::{App, BrowseNeighborhoods, Toggle3Zoomed, Transition}; // TODO Share structure or pieces with Ungap's predict mode // ... can't we just produce data of a certain shape, and have a UI pretty tuned for that? pub struct ShowResults { draw_all_neighborhoods: Drawable, - draw_all_filters: ToggleZoomed, + draw_all_filters: Toggle3Zoomed, } impl ShowResults { diff --git a/ltn/src/lib.rs b/ltn/src/lib.rs index 6bee34777b..4ce4a66bd6 100644 --- a/ltn/src/lib.rs +++ b/ltn/src/lib.rs @@ -5,7 +5,7 @@ use structopt::StructOpt; use widgetry::{GfxCtx, Settings}; pub use browse::BrowseNeighborhoods; -pub use filters::{DiagonalFilter, ModalFilters}; +pub use filters::{DiagonalFilter, ModalFilters, Toggle3Zoomed}; pub use neighborhood::{Cell, DistanceInterval, Neighborhood}; pub use partition::{NeighborhoodID, Partitioning}; @@ -63,7 +63,7 @@ fn run(mut settings: Settings) { impact: impact::Impact::empty(ctx), - highlight_boundary_roads: true, + highlight_boundary_roads: false, draw_neighborhood_style: browse::Style::SimpleColoring, draw_cells_as_areas: true, draw_borders_as_arrows: true, diff --git a/ltn/src/neighborhood.rs b/ltn/src/neighborhood.rs index 7adc82dd14..aa9f0a96df 100644 --- a/ltn/src/neighborhood.rs +++ b/ltn/src/neighborhood.rs @@ -5,10 +5,9 @@ use maplit::btreeset; use geom::{Distance, Polygon}; use map_gui::tools::DrawRoadLabels; use map_model::{IntersectionID, Map, PathConstraints, Perimeter, RoadID}; -use widgetry::mapspace::ToggleZoomed; use widgetry::{Drawable, EventCtx, GeomBatch}; -use crate::{App, ModalFilters, NeighborhoodID}; +use crate::{App, ModalFilters, NeighborhoodID, Toggle3Zoomed}; pub struct Neighborhood { pub id: NeighborhoodID, @@ -24,7 +23,7 @@ pub struct Neighborhood { pub cells: Vec, pub fade_irrelevant: Drawable, - pub draw_filters: ToggleZoomed, + pub draw_filters: Toggle3Zoomed, pub labels: DrawRoadLabels, } @@ -74,7 +73,7 @@ impl Neighborhood { cells: Vec::new(), fade_irrelevant: Drawable::empty(ctx), - draw_filters: ToggleZoomed::empty(ctx), + draw_filters: Toggle3Zoomed::empty(ctx), // Temporary value labels: DrawRoadLabels::only_major_roads(), };