A skeleton emerges, from whatever sort of place skeletons lurk

This commit is contained in:
Dustin Carlino 2021-08-03 11:58:02 -07:00
parent 58f9c912cc
commit c019304ee3
4 changed files with 166 additions and 13 deletions

View File

@ -30,6 +30,7 @@ mod info;
mod layer;
mod pregame;
mod sandbox;
mod ungap;
pub fn main() {
let settings = Settings::new("A/B Street");
@ -46,6 +47,7 @@ struct Setup {
start_time: Option<Duration>,
load_kml: Option<String>,
diff_map: Option<String>,
ungap: bool,
}
fn run(mut settings: Settings) {
@ -76,6 +78,7 @@ fn run(mut settings: Settings) {
start_time: args.optional_parse("--time", |t| Duration::parse(t)),
load_kml: args.optional("--kml"),
diff_map: args.optional("--diff"),
ungap: args.enabled("--ungap"),
};
settings = settings.canvas_settings(setup.opts.canvas_settings.clone());
@ -153,7 +156,8 @@ fn setup_app(ctx: &mut EventCtx, mut setup: Setup) -> (App, Vec<Box<dyn State<Ap
let title = !setup.opts.dev
&& !setup.flags.sim_flags.load.contains("player/save")
&& !setup.flags.sim_flags.load.contains("/scenarios/")
&& setup.maybe_mode.is_none();
&& setup.maybe_mode.is_none()
&& !setup.ungap;
// 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() {
@ -353,6 +357,8 @@ fn finish_app_setup(
} else {
vec![SandboxMode::simple_new(app, mode)]
}
} else if setup.ungap {
vec![ungap::ExploreMap::new_state(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

150
game/src/ungap/mod.rs Normal file
View File

@ -0,0 +1,150 @@
use geom::{Circle, Distance, Pt2D};
use map_gui::tools::{nice_map_name, CityPicker, PopupMsg};
use widgetry::{
lctrl, Color, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel,
State, VerticalAlignment, Widget,
};
use crate::app::{App, Transition};
pub struct ExploreMap {
top_panel: Panel,
legend: Panel,
}
impl ExploreMap {
pub fn new_state(ctx: &mut EventCtx, app: &App) -> Box<dyn State<App>> {
Box::new(ExploreMap {
top_panel: make_top_panel(ctx),
legend: make_legend(ctx, app),
})
}
}
impl State<App> for ExploreMap {
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
ctx.canvas_movement();
if let Outcome::Clicked(x) = self.top_panel.event(ctx) {
match x.as_ref() {
"about A/B Street" => {
return Transition::Push(PopupMsg::new_state(ctx, "TODO", vec!["TODO"]));
}
"Bike Master Plan" => {
return Transition::Push(PopupMsg::new_state(ctx, "TODO", vec!["TODO"]));
}
"Edit network" => {
return Transition::Push(PopupMsg::new_state(ctx, "TODO", vec!["TODO"]));
}
_ => unreachable!(),
}
}
if let Outcome::Clicked(x) = self.legend.event(ctx) {
return Transition::Push(match x.as_ref() {
"change map" => CityPicker::new_state(
ctx,
app,
Box::new(|ctx, app| {
Transition::Multi(vec![Transition::Pop, Transition::Replace(ExploreMap::new_state(ctx, app))])
}),
),
// TODO Add physical picture examples
"highway" => PopupMsg::new_state(ctx, "Highways", vec!["Unless there's a separate trail (like on the 520 or I90 bridge), highways aren't accessible to biking"]),
"major street" => PopupMsg::new_state(ctx, "Major streets", vec!["Arterials have more traffic, but are often where businesses are located"]),
"minor street" => PopupMsg::new_state(ctx, "Minor streets", vec!["Local streets have a low volume of traffic and are usually comfortable for biking, even without dedicated infrastructure"]),
"trail" => PopupMsg::new_state(ctx, "Trails", vec!["Trails like the Burke Gilman are usually well-separated from vehicle traffic. The space is usually shared between people walking, cycling, and rolling."]),
"protected bike lane" => PopupMsg::new_state(ctx, "Protected bike lanes", vec!["Bike lanes separated from vehicle traffic by physical barriers or a few feet of striping"]),
"painted bike lane" => PopupMsg::new_state(ctx, "Painted bike lanes", vec!["Bike lanes without any separation from vehicle traffic. Often uncomfortably close to the \"door zone\" of parked cars."]),
"Stay Healthy Street / greenway" => PopupMsg::new_state(ctx, "Stay Healthy Streets and neighborhood greenways", vec!["Residential streets with additional signage and light barriers. These are intended to be low traffic, dedicated for people walking and biking."]),
_ => unreachable!(),
});
}
Transition::Keep
}
fn draw(&self, g: &mut GfxCtx, _: &App) {
self.top_panel.draw(g);
self.legend.draw(g);
}
}
fn make_top_panel(ctx: &mut EventCtx) -> Panel {
Panel::new_builder(Widget::row(vec![
ctx.style()
.btn_plain
.btn()
.image_path("system/assets/pregame/logo.svg")
.image_dims(50.0)
.build_widget(ctx, "about A/B Street"),
// TODO Tab style?
ctx.style()
.btn_solid_primary
.text("Today")
.disabled(true)
.build_def(ctx)
.centered_vert(),
ctx.style()
.btn_solid_primary
.text("Bike Master Plan")
.build_def(ctx)
.centered_vert(),
ctx.style()
.btn_solid_primary
.icon_text("system/assets/tools/pencil.svg", "Edit network")
.build_def(ctx)
.centered_vert(),
]))
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
.build(ctx)
}
fn make_legend(ctx: &mut EventCtx, app: &App) -> Panel {
Panel::new_builder(Widget::col(vec![
Widget::custom_row(vec![
Line("Bike Network")
.small_heading()
.into_widget(ctx)
.margin_right(18),
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")
.margin_right(8),
]),
legend(ctx, app.cs.unzoomed_highway, "highway"),
legend(ctx, app.cs.unzoomed_arterial, "major street"),
legend(ctx, app.cs.unzoomed_residential, "minor street"),
legend(ctx, app.cs.unzoomed_trail, "trail"),
// TODO Untuned colors
legend(ctx, Color::hex("#74B0FC"), "protected bike lane"),
legend(ctx, Color::GREEN, "painted bike lane"),
legend(ctx, Color::BLUE, "Stay Healthy Street / greenway"),
// TODO Distinguish door-zone bike lanes?
// TODO Call out bike turning boxes?
// TODO Call out bike signals?
]))
.aligned(HorizontalAlignment::Right, VerticalAlignment::Bottom)
.build(ctx)
}
fn legend(ctx: &mut EventCtx, color: Color, label: &str) -> Widget {
let radius = 15.0;
Widget::row(vec![
GeomBatch::from(vec![(
color,
Circle::new(Pt2D::new(radius, radius), Distance::meters(radius)).to_polygon(),
)])
.into_widget(ctx)
.centered_vert(),
ctx.style()
.btn_plain
.text(label)
.build_def(ctx)
.centered_vert(),
])
}

View File

@ -78,9 +78,9 @@ pub struct ColorScheme {
pub road_center_line: Color,
pub light_rail_track: Color,
pub private_road: Color,
unzoomed_highway: Color,
unzoomed_arterial: Color,
unzoomed_residential: Color,
pub unzoomed_highway: Color,
pub unzoomed_arterial: Color,
pub unzoomed_residential: Color,
pub unzoomed_trail: Color,
// Intersections

View File

@ -205,15 +205,12 @@ pub fn collapse_intersection(raw: &mut RawMap, i: NodeID) {
// When we concatenate the points, the common point will be duplicated
new_road.center_points.dedup();
let new_r1 =
OriginalRoad {
osm_way_id: r1.osm_way_id,
i1: new_i1,
i2: new_i2,
};
raw.roads.insert(new_r1,
new_road,
);
let new_r1 = OriginalRoad {
osm_way_id: r1.osm_way_id,
i1: new_i1,
i2: new_i2,
};
raw.roads.insert(new_r1, new_road);
// We may need to fix up turn restrictions. r1 and r2 both become new_r1.
let rewrite = |x: &OriginalRoad| *x == r1 || *x == r2;