mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +03:00
Start LTN tool from the command line. Add a map switcher, so it's usable
standalone. (It might be worth splitting this out to a separate crate, but not yet) Also refactor the fading from some of the colorer tools
This commit is contained in:
parent
72e2b39301
commit
8470403d74
@ -29,7 +29,6 @@ pub use self::routes::PathCostDebugger;
|
||||
|
||||
mod blocked_by;
|
||||
mod floodfill;
|
||||
mod ltn;
|
||||
mod objects;
|
||||
pub mod path_counter;
|
||||
mod polygons;
|
||||
@ -611,7 +610,6 @@ impl ContextualActions for Actions {
|
||||
if cfg!(not(target_arch = "wasm32")) {
|
||||
actions.push((Key::M, "merge short segment".to_string()));
|
||||
}
|
||||
actions.push((Key::L, "LTN mode".to_string()));
|
||||
}
|
||||
ID::Intersection(i) => {
|
||||
actions.push((Key::H, "hide this".to_string()));
|
||||
@ -813,9 +811,6 @@ impl ContextualActions for Actions {
|
||||
abstio::write_json("merge_osm_ways.json".to_string(), &ways);
|
||||
Transition::Push(reimport_map(ctx, app, Some(orig_ways)))
|
||||
}
|
||||
(ID::Lane(l), "LTN mode") => {
|
||||
Transition::Push(ltn::Viewer::start_from_road(ctx, app, l.road))
|
||||
}
|
||||
(ID::Area(a), "debug area geometry") => {
|
||||
let pts = &app.primary.map.get_a(a).polygon.points();
|
||||
let center = if pts[0] == *pts.last().unwrap() {
|
||||
|
@ -29,6 +29,7 @@ mod devtools;
|
||||
mod edit;
|
||||
mod info;
|
||||
mod layer;
|
||||
mod ltn;
|
||||
mod pregame;
|
||||
mod sandbox;
|
||||
mod ungap;
|
||||
@ -49,6 +50,7 @@ struct Setup {
|
||||
load_kml: Option<String>,
|
||||
diff_map: Option<String>,
|
||||
ungap: bool,
|
||||
ltn: bool,
|
||||
}
|
||||
|
||||
fn run(mut settings: Settings) {
|
||||
@ -80,6 +82,7 @@ fn run(mut settings: Settings) {
|
||||
load_kml: args.optional("--kml"),
|
||||
diff_map: args.optional("--diff"),
|
||||
ungap: args.enabled("--ungap"),
|
||||
ltn: args.enabled("--ltn"),
|
||||
};
|
||||
|
||||
settings = settings.canvas_settings(setup.opts.canvas_settings.clone());
|
||||
@ -158,7 +161,8 @@ fn setup_app(ctx: &mut EventCtx, mut setup: Setup) -> (App, Vec<Box<dyn State<Ap
|
||||
&& !setup.flags.sim_flags.load.contains("player/save")
|
||||
&& !setup.flags.sim_flags.load.contains("/scenarios/")
|
||||
&& setup.maybe_mode.is_none()
|
||||
&& !setup.ungap;
|
||||
&& !setup.ungap
|
||||
&& !setup.ltn;
|
||||
|
||||
// Load the map used previously if we're starting on the title screen without any overrides.
|
||||
if title && setup.flags.sim_flags.load == MapName::seattle("montlake").path() {
|
||||
@ -184,7 +188,7 @@ fn setup_app(ctx: &mut EventCtx, mut setup: Setup) -> (App, Vec<Box<dyn State<Ap
|
||||
if title {
|
||||
setup.opts.color_scheme = map_gui::colors::ColorSchemeChoice::Pregame;
|
||||
}
|
||||
if setup.ungap {
|
||||
if setup.ungap || setup.ltn {
|
||||
setup.opts.color_scheme = map_gui::colors::ColorSchemeChoice::DayMode;
|
||||
}
|
||||
let cs = map_gui::colors::ColorScheme::new(ctx, setup.opts.color_scheme);
|
||||
@ -415,6 +419,8 @@ fn finish_app_setup(
|
||||
} else if setup.ungap {
|
||||
let layers = ungap::Layers::new(ctx, app);
|
||||
vec![ungap::ExploreMap::new_state(ctx, app, layers)]
|
||||
} else if setup.ltn {
|
||||
vec![ltn::Viewer::start_anywhere(ctx, app)]
|
||||
} else {
|
||||
// Not attempting to keep the primary and secondary simulations synchronized at the same
|
||||
// time yet. Just handle this one startup case, so we can switch maps without constantly
|
||||
|
@ -4,7 +4,7 @@ use geom::Distance;
|
||||
use map_model::osm::RoadRank;
|
||||
use map_model::{IntersectionID, Map, PathConstraints, RoadID};
|
||||
|
||||
use crate::debug::ltn::{Neighborhood, RatRun};
|
||||
use crate::ltn::{Neighborhood, RatRun};
|
||||
|
||||
impl Neighborhood {
|
||||
// TODO Doesn't find the full perimeter. But do we really need that?
|
@ -1,11 +1,11 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use map_gui::tools::ColorDiscrete;
|
||||
use map_gui::tools::{nice_map_name, CityPicker, ColorDiscrete};
|
||||
use map_gui::ID;
|
||||
use map_model::{IntersectionID, Map, Road, RoadID};
|
||||
use widgetry::{
|
||||
Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel,
|
||||
State, Text, TextExt, VerticalAlignment, Widget,
|
||||
lctrl, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome,
|
||||
Panel, State, Text, TextExt, VerticalAlignment, Widget,
|
||||
};
|
||||
|
||||
use crate::app::{App, Transition};
|
||||
@ -37,14 +37,34 @@ struct RatRun {
|
||||
}
|
||||
|
||||
impl Viewer {
|
||||
pub fn start_from_road(ctx: &mut EventCtx, app: &App, start: RoadID) -> Box<dyn State<App>> {
|
||||
pub fn start_anywhere(ctx: &mut EventCtx, app: &App) -> Box<dyn State<App>> {
|
||||
// Find some residential road to start on
|
||||
let r = app
|
||||
.primary
|
||||
.map
|
||||
.all_roads()
|
||||
.iter()
|
||||
.find(|r| r.get_rank() == map_model::osm::RoadRank::Local)
|
||||
.unwrap();
|
||||
Viewer::start_from_road(ctx, app, r.id)
|
||||
}
|
||||
|
||||
fn start_from_road(ctx: &mut EventCtx, app: &App, start: RoadID) -> Box<dyn State<App>> {
|
||||
let neighborhood = Neighborhood::from_road(&app.primary.map, start);
|
||||
let (draw_neighborhood, legend) = neighborhood.render(ctx, app);
|
||||
let rat_runs = neighborhood.find_rat_runs(&app.primary.map);
|
||||
let panel = Panel::new_builder(Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Line("LTN tool").small_heading().into_widget(ctx),
|
||||
ctx.style().btn_close_widget(ctx),
|
||||
ctx.style()
|
||||
.btn_popup_icon_text(
|
||||
"system/assets/tools/map.svg",
|
||||
nice_map_name(app.primary.map.get_name()),
|
||||
)
|
||||
.hotkey(lctrl(Key::L))
|
||||
.build_widget(ctx, "change map")
|
||||
.centered_vert()
|
||||
.align_right(),
|
||||
]),
|
||||
legend,
|
||||
"Click a road to re-center".text_widget(ctx),
|
||||
@ -134,8 +154,12 @@ impl State<App> for Viewer {
|
||||
|
||||
if let Outcome::Clicked(x) = self.panel.event(ctx) {
|
||||
match x.as_ref() {
|
||||
"close" => {
|
||||
return Transition::Pop;
|
||||
"change map" => {
|
||||
return Transition::Push(CityPicker::new_state(
|
||||
ctx,
|
||||
app,
|
||||
Box::new(|ctx, app| Transition::Replace(Viewer::start_anywhere(ctx, app))),
|
||||
));
|
||||
}
|
||||
"previous rat run" => {
|
||||
self.current_idx -= 1;
|
||||
@ -164,7 +188,7 @@ impl Neighborhood {
|
||||
let interior = Color::BLUE;
|
||||
let perimeter = Color::hex("#40B5AD");
|
||||
let border = Color::CYAN;
|
||||
let mut colorer = ColorDiscrete::new(
|
||||
let mut colorer = ColorDiscrete::no_fading(
|
||||
app,
|
||||
vec![
|
||||
("interior", interior),
|
@ -165,6 +165,7 @@ impl Layers {
|
||||
crate::layer::elevation::SteepStreets::make_colorer(ctx, app);
|
||||
// The Colorer fades the map as the very first thing in the batch, but we
|
||||
// don't want to do that twice.
|
||||
// TODO Can't use no_fading without complicating make_colorer...
|
||||
colorer.unzoomed.shift();
|
||||
self.steep_streets = Some(colorer.unzoomed.upload(ctx));
|
||||
} else {
|
||||
|
@ -464,11 +464,8 @@ impl ModeShiftData {
|
||||
// And convert grams to tons
|
||||
self.results.annual_co2_emissions_tons = 404.0 * annual_mileage / 907185.0;
|
||||
|
||||
let mut colorer = ColorNetwork::new(app);
|
||||
let mut colorer = ColorNetwork::no_fading(app);
|
||||
colorer.ranked_roads(count_per_road.clone(), &app.cs.good_to_bad_red);
|
||||
// The Colorer fades the map as the very first thing in the batch, but we don't want to do
|
||||
// that twice.
|
||||
colorer.unzoomed.shift();
|
||||
let (draw_unzoomed, draw_zoomed) = colorer.build(ctx);
|
||||
self.gaps = NetworkGaps {
|
||||
draw_unzoomed,
|
||||
|
@ -38,6 +38,15 @@ impl<'a> ColorDiscrete<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn no_fading<I: Into<String>>(
|
||||
app: &'a dyn AppLike,
|
||||
categories: Vec<(I, Color)>,
|
||||
) -> ColorDiscrete<'a> {
|
||||
let mut c = ColorDiscrete::new(app, categories);
|
||||
c.unzoomed = GeomBatch::new();
|
||||
c
|
||||
}
|
||||
|
||||
pub fn add_l<I: AsRef<str>>(&mut self, l: LaneID, category: I) {
|
||||
let color = self.colors[category.as_ref()];
|
||||
self.unzoomed
|
||||
@ -270,6 +279,14 @@ impl<'a> ColorNetwork<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn no_fading(app: &'a dyn AppLike) -> ColorNetwork {
|
||||
ColorNetwork {
|
||||
map: app.map(),
|
||||
unzoomed: GeomBatch::new(),
|
||||
zoomed: GeomBatch::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_l(&mut self, l: LaneID, color: Color) {
|
||||
self.unzoomed
|
||||
.push(color, self.map.get_parent(l).get_thick_polygon());
|
||||
|
Loading…
Reference in New Issue
Block a user