From 57d1cba40c3d37c13824109ebc7bc978c7f68cf9 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Thu, 26 Aug 2021 09:18:12 -0700 Subject: [PATCH] Share the logo / map changer in the 3 modes too --- game/src/ungap/mod.rs | 164 +++++++++++++++++---------------- game/src/ungap/quick_sketch.rs | 29 ++++-- game/src/ungap/route.rs | 32 +++++-- 3 files changed, 131 insertions(+), 94 deletions(-) diff --git a/game/src/ungap/mod.rs b/game/src/ungap/mod.rs index 60bf3c0dab..4594663840 100644 --- a/game/src/ungap/mod.rs +++ b/game/src/ungap/mod.rs @@ -110,26 +110,7 @@ impl State for ExploreMap { if let Outcome::Clicked(x) = self.top_panel.event(ctx) { match x.as_ref() { "about A/B Street" => { - let panel = Panel::new_builder(Widget::col(vec![ - Widget::row(vec![ - Line("About A/B Street").small_heading().into_widget(ctx), - ctx.style().btn_close_widget(ctx), - ]), - Text::from_multiline(vec![ - Line("Created by Dustin Carlino, Yuwen Li, & Michael Kirk").small(), - Line("Data from OpenStreetMap, King County GIS, King County LIDAR") - .small(), - ]) - .into_widget(ctx), - "This is a simplified version. Check out the full version below." - .text_widget(ctx), - ctx.style().btn_outline.text("abstreet.org").build_def(ctx), - ])) - .build(ctx); - return Transition::Push(>::new_state( - panel, - Box::new(About), - )); + return Transition::Push(About::new_state(ctx)); } "change map" => { return Transition::Push(CityPicker::new_state( @@ -144,6 +125,28 @@ impl State for ExploreMap { }), )); } + "Create new bike lanes" => { + app.primary.current_selection = None; + return Transition::ConsumeState(Box::new(|state, ctx, app| { + let state = state.downcast::().ok().unwrap(); + vec![crate::ungap::quick_sketch::QuickSketch::new_state( + ctx, + app, + state.layers, + )] + })); + } + "Plan a route" => { + app.primary.current_selection = None; + return Transition::ConsumeState(Box::new(|state, ctx, app| { + let state = state.downcast::().ok().unwrap(); + vec![crate::ungap::route::RoutePlanner::new_state( + ctx, + app, + state.layers, + )] + })); + } "Open a proposal" => { // Dummy mode, just to allow all edits // TODO Actually, should we make one to express that only road edits are @@ -168,28 +171,6 @@ impl State for ExploreMap { "Share proposal" => { return Transition::Push(share::upload_proposal(ctx, app)); } - "Create new bike lanes" => { - app.primary.current_selection = None; - return Transition::ConsumeState(Box::new(|state, ctx, app| { - let state = state.downcast::().ok().unwrap(); - vec![crate::ungap::quick_sketch::QuickSketch::new_state( - ctx, - app, - state.layers, - )] - })); - } - "Plan a route" => { - app.primary.current_selection = None; - return Transition::ConsumeState(Box::new(|state, ctx, app| { - let state = state.downcast::().ok().unwrap(); - vec![crate::ungap::route::RoutePlanner::new_state( - ctx, - app, - state.layers, - )] - })); - } _ => unreachable!(), } } @@ -276,25 +257,7 @@ fn make_top_panel(ctx: &mut EventCtx, app: &App) -> Panel { // TODO Should undo/redo, save, share functionality also live here? Panel::new_builder(Widget::col(vec![ - Widget::row(vec![ - ctx.style() - .btn_plain - .btn() - .image_path("system/assets/pregame/logo.svg") - .image_dims(70.0) - .build_widget(ctx, "about A/B Street"), - Widget::col(vec![ - Line("Ungap the Map").small_heading().into_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"), - ]), - ]), - make_tabs(ctx, Tab::Explore), + make_header(ctx, app, Tab::Explore), Widget::col(file_management).section(ctx), ])) .aligned(HorizontalAlignment::Left, VerticalAlignment::Top) @@ -303,6 +266,26 @@ fn make_top_panel(ctx: &mut EventCtx, app: &App) -> Panel { struct About; +impl About { + pub fn new_state(ctx: &mut EventCtx) -> Box> { + let panel = Panel::new_builder(Widget::col(vec![ + Widget::row(vec![ + Line("About A/B Street").small_heading().into_widget(ctx), + ctx.style().btn_close_widget(ctx), + ]), + Text::from_multiline(vec![ + Line("Created by Dustin Carlino, Yuwen Li, & Michael Kirk").small(), + Line("Data from OpenStreetMap, King County GIS, King County LIDAR").small(), + ]) + .into_widget(ctx), + "This is a simplified version. Check out the full version below.".text_widget(ctx), + ctx.style().btn_outline.text("abstreet.org").build_def(ctx), + ])) + .build(ctx); + >::new_state(panel, Box::new(About)) + } +} + impl SimpleState for About { fn on_click(&mut self, _: &mut EventCtx, _: &mut App, x: &str, _: &Panel) -> Transition { if x == "close" { @@ -326,25 +309,44 @@ pub enum Tab { Route, } -pub fn make_tabs(ctx: &mut EventCtx, current_tab: Tab) -> Widget { - Widget::row(vec![ - ctx.style() - .btn_tab - .icon_text("system/assets/tools/pan.svg", "Explore") - .hotkey(Key::E) - .disabled(current_tab == Tab::Explore) - .build_def(ctx), - ctx.style() - .btn_tab - .icon_text("system/assets/tools/pencil.svg", "Create new bike lanes") - .hotkey(Key::C) - .disabled(current_tab == Tab::Create) - .build_def(ctx), - ctx.style() - .btn_tab - .icon_text("system/assets/tools/pin.svg", "Plan a route") - .hotkey(Key::R) - .disabled(current_tab == Tab::Route) - .build_def(ctx), +pub fn make_header(ctx: &mut EventCtx, app: &App, current_tab: Tab) -> Widget { + Widget::col(vec![ + 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"), + 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(), + ]), + Widget::row(vec![ + ctx.style() + .btn_tab + .icon_text("system/assets/tools/pan.svg", "Explore") + .hotkey(Key::E) + .disabled(current_tab == Tab::Explore) + .build_def(ctx), + ctx.style() + .btn_tab + .icon_text("system/assets/tools/pencil.svg", "Create new bike lanes") + .hotkey(Key::C) + .disabled(current_tab == Tab::Create) + .build_def(ctx), + ctx.style() + .btn_tab + .icon_text("system/assets/tools/pin.svg", "Plan a route") + .hotkey(Key::R) + .disabled(current_tab == Tab::Route) + .build_def(ctx), + ]), ]) } diff --git a/game/src/ungap/quick_sketch.rs b/game/src/ungap/quick_sketch.rs index e661bdb431..40d5306a90 100644 --- a/game/src/ungap/quick_sketch.rs +++ b/game/src/ungap/quick_sketch.rs @@ -1,5 +1,5 @@ use abstutil::Tags; -use map_gui::tools::PopupMsg; +use map_gui::tools::{CityPicker, PopupMsg}; use map_model::{BufferType, Direction, EditCmd, EditRoad, LaneSpec, LaneType, RoadID}; use widgetry::{ Choice, EventCtx, GfxCtx, HorizontalAlignment, Key, Outcome, Panel, State, TextExt, @@ -9,7 +9,7 @@ use widgetry::{ use crate::app::{App, Transition}; use crate::common::RouteSketcher; use crate::edit::apply_map_edits; -use crate::ungap::{make_tabs, Layers, Tab}; +use crate::ungap::{make_header, Layers, Tab}; pub struct QuickSketch { top_panel: Panel, @@ -24,13 +24,13 @@ impl QuickSketch { layers, route_sketcher: RouteSketcher::new(ctx, app), }; - qs.update_top_panel(ctx); + qs.update_top_panel(ctx, app); Box::new(qs) } - fn update_top_panel(&mut self, ctx: &mut EventCtx) { + fn update_top_panel(&mut self, ctx: &mut EventCtx, app: &App) { let mut col = vec![ - make_tabs(ctx, Tab::Create), + make_header(ctx, app, Tab::Create), self.route_sketcher.get_widget_to_describe(ctx), ]; @@ -80,6 +80,23 @@ impl State for QuickSketch { fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition { if let Outcome::Clicked(x) = self.top_panel.event(ctx) { match x.as_ref() { + "about A/B Street" => { + return Transition::Push(crate::ungap::About::new_state(ctx)); + } + "change map" => { + return Transition::Push(CityPicker::new_state( + ctx, + app, + Box::new(|ctx, app| { + Transition::Multi(vec![ + Transition::Pop, + // Since we're totally changing maps, don't reuse the Layers + // TODO Should we keep the current tab or always reset here? + Transition::Replace(crate::ungap::ExploreMap::launch(ctx, app)), + ]) + }), + )); + } "Explore" => { return Transition::ConsumeState(Box::new(|state, ctx, app| { let state = state.downcast::().ok().unwrap(); @@ -116,7 +133,7 @@ impl State for QuickSketch { } if self.route_sketcher.event(ctx, app) { - self.update_top_panel(ctx); + self.update_top_panel(ctx, app); } if let Some(t) = self.layers.event(ctx, app) { diff --git a/game/src/ungap/route.rs b/game/src/ungap/route.rs index 6ad3b73d18..31d29d849f 100644 --- a/game/src/ungap/route.rs +++ b/game/src/ungap/route.rs @@ -5,6 +5,7 @@ use rand::SeedableRng; use rand_xorshift::XorShiftRng; use geom::{Circle, Distance, Duration, FindClosest, Polygon}; +use map_gui::tools::CityPicker; use map_model::{PathStep, NORMAL_LANE_THICKNESS}; use sim::{TripEndpoint, TripMode}; use widgetry::{ @@ -13,7 +14,7 @@ use widgetry::{ }; use crate::app::{App, Transition}; -use crate::ungap::{make_tabs, Layers, Tab}; +use crate::ungap::{make_header, Layers, Tab}; pub struct RoutePlanner { layers: Layers, @@ -74,14 +75,14 @@ impl RoutePlanner { draw_route: Drawable::empty(ctx), results_panel: Panel::empty(ctx), }; - rp.update_input_panel(ctx); + rp.update_input_panel(ctx, app); rp.update_waypoints_drawable(ctx); rp.update_route(ctx, app); Box::new(rp) } - fn update_input_panel(&mut self, ctx: &mut EventCtx) { - let mut col = vec![make_tabs(ctx, Tab::Route)]; + fn update_input_panel(&mut self, ctx: &mut EventCtx, app: &App) { + let mut col = vec![make_header(ctx, app, Tab::Route)]; for (idx, waypt) in self.waypoints.iter().enumerate() { col.push(Widget::row(vec![ @@ -162,7 +163,7 @@ impl RoutePlanner { let idx = self.hovering_on_waypt.unwrap(); if self.waypoints[idx].at != at { self.waypoints[idx] = Waypoint::new(ctx, app, at, idx); - self.update_input_panel(ctx); + self.update_input_panel(ctx, app); self.update_waypoints_drawable(ctx); self.update_route(ctx, app); } @@ -345,6 +346,23 @@ impl State for RoutePlanner { if let Outcome::Clicked(x) = self.input_panel.event(ctx) { match x.as_ref() { + "about A/B Street" => { + return Transition::Push(crate::ungap::About::new_state(ctx)); + } + "change map" => { + return Transition::Push(CityPicker::new_state( + ctx, + app, + Box::new(|ctx, app| { + Transition::Multi(vec![ + Transition::Pop, + // Since we're totally changing maps, don't reuse the Layers + // TODO Should we keep the current tab or always reset here? + Transition::Replace(crate::ungap::ExploreMap::launch(ctx, app)), + ]) + }), + )); + } "Explore" => { return Transition::ConsumeState(Box::new(|state, ctx, app| { let state = state.downcast::().ok().unwrap(); @@ -363,7 +381,7 @@ impl State for RoutePlanner { } "Add waypoint" => { self.waypoints.push(self.make_new_waypt(ctx, app)); - self.update_input_panel(ctx); + self.update_input_panel(ctx, app); self.update_waypoints_drawable(ctx); self.update_route(ctx, app); self.update_hover(ctx); @@ -377,7 +395,7 @@ impl State for RoutePlanner { *waypt = Waypoint::new(ctx, app, waypt.at, idx); } - self.update_input_panel(ctx); + self.update_input_panel(ctx, app); self.update_waypoints_drawable(ctx); self.update_route(ctx, app); } else {