mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 07:25:47 +03:00
Move some misc stuff from game/common to map_gui, so LTN can use it
LTN crate builds, and appears to work!
This commit is contained in:
parent
8dc2c68760
commit
a6cd58346f
@ -1,9 +1,7 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use geom::{Distance, Duration, Polygon, Time};
|
||||
use geom::{Duration, Polygon, Time};
|
||||
use map_gui::ID;
|
||||
use map_model::{IntersectionID, Map, RoadID};
|
||||
use sim::{AgentType, TripMode, TripPhaseType};
|
||||
use widgetry::{
|
||||
lctrl, Color, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Panel, ScreenDims,
|
||||
@ -13,7 +11,6 @@ use widgetry::{
|
||||
pub use self::route_sketcher::RouteSketcher;
|
||||
pub use self::select::RoadSelector;
|
||||
pub use self::warp::{warp_to_id, Warping};
|
||||
pub use self::waypoints::{InputWaypoints, WaypointID};
|
||||
use crate::app::App;
|
||||
use crate::app::Transition;
|
||||
use crate::info::{ContextualActions, InfoPanel, Tab};
|
||||
@ -23,7 +20,6 @@ mod route_sketcher;
|
||||
mod select;
|
||||
pub mod share;
|
||||
mod warp;
|
||||
mod waypoints;
|
||||
|
||||
// TODO This is now just used in two modes...
|
||||
pub struct CommonState {
|
||||
@ -370,55 +366,6 @@ pub fn cmp_duration_shorter(app: &App, after: Duration, before: Duration) -> Vec
|
||||
}
|
||||
}
|
||||
|
||||
/// Shorter is better
|
||||
pub fn cmp_dist(txt: &mut Text, app: &App, dist: Distance, shorter: &str, longer: &str) {
|
||||
match dist.cmp(&Distance::ZERO) {
|
||||
Ordering::Less => {
|
||||
txt.add_line(
|
||||
Line(format!(
|
||||
"{} {}",
|
||||
(-dist).to_string(&app.opts.units),
|
||||
shorter
|
||||
))
|
||||
.fg(Color::GREEN),
|
||||
);
|
||||
}
|
||||
Ordering::Greater => {
|
||||
txt.add_line(
|
||||
Line(format!("{} {}", dist.to_string(&app.opts.units), longer)).fg(Color::RED),
|
||||
);
|
||||
}
|
||||
Ordering::Equal => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Shorter is better
|
||||
pub fn cmp_duration(txt: &mut Text, app: &App, duration: Duration, shorter: &str, longer: &str) {
|
||||
match duration.cmp(&Duration::ZERO) {
|
||||
Ordering::Less => {
|
||||
txt.add_line(
|
||||
Line(format!(
|
||||
"{} {}",
|
||||
(-duration).to_string(&app.opts.units),
|
||||
shorter
|
||||
))
|
||||
.fg(Color::GREEN),
|
||||
);
|
||||
}
|
||||
Ordering::Greater => {
|
||||
txt.add_line(
|
||||
Line(format!(
|
||||
"{} {}",
|
||||
duration.to_string(&app.opts.units),
|
||||
longer
|
||||
))
|
||||
.fg(Color::RED),
|
||||
);
|
||||
}
|
||||
Ordering::Equal => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn color_for_mode(app: &App, m: TripMode) -> Color {
|
||||
match m {
|
||||
TripMode::Walk => app.cs.unzoomed_pedestrian,
|
||||
@ -451,22 +398,6 @@ pub fn color_for_trip_phase(app: &App, tpt: TripPhaseType) -> Color {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn intersections_from_roads(roads: &BTreeSet<RoadID>, map: &Map) -> BTreeSet<IntersectionID> {
|
||||
let mut results = BTreeSet::new();
|
||||
for r in roads {
|
||||
let r = map.get_r(*r);
|
||||
for i in [r.src_i, r.dst_i] {
|
||||
if results.contains(&i) {
|
||||
continue;
|
||||
}
|
||||
if map.get_i(i).roads.iter().all(|r| roads.contains(r)) {
|
||||
results.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
results
|
||||
}
|
||||
|
||||
pub fn checkbox_per_mode(
|
||||
ctx: &mut EventCtx,
|
||||
app: &App,
|
||||
@ -511,28 +442,3 @@ pub fn jump_to_time_upon_startup(
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn percentage_bar(ctx: &EventCtx, txt: Text, pct_green: f64) -> Widget {
|
||||
let bad_color = Color::RED;
|
||||
let good_color = Color::GREEN;
|
||||
|
||||
let total_width = 450.0;
|
||||
let height = 32.0;
|
||||
let radius = 4.0;
|
||||
|
||||
let mut batch = GeomBatch::new();
|
||||
// Background
|
||||
batch.push(
|
||||
bad_color,
|
||||
Polygon::rounded_rectangle(total_width, height, radius),
|
||||
);
|
||||
// Foreground
|
||||
if let Some(poly) = Polygon::maybe_rounded_rectangle(pct_green * total_width, height, radius) {
|
||||
batch.push(good_color, poly);
|
||||
}
|
||||
// Text
|
||||
let label = txt.render_autocropped(ctx);
|
||||
let dims = label.get_dims();
|
||||
batch.append(label.translate(10.0, height / 2.0 - dims.height / 2.0));
|
||||
batch.into_widget(ctx)
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use map_gui::tools::intersections_from_roads;
|
||||
use map_gui::ID;
|
||||
use map_model::{IntersectionID, RoadID};
|
||||
use widgetry::{Color, Drawable, EventCtx, GeomBatch, GfxCtx, Key, RewriteColor, Widget};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::common::{intersections_from_roads, CommonState};
|
||||
use crate::common::CommonState;
|
||||
|
||||
/// A tool for selecting multiple roads.
|
||||
pub struct RoadSelector {
|
||||
|
@ -3,7 +3,7 @@ use std::collections::BTreeSet;
|
||||
use enumset::EnumSet;
|
||||
use maplit::btreeset;
|
||||
|
||||
use map_gui::tools::ColorDiscrete;
|
||||
use map_gui::tools::{intersections_from_roads, ColorDiscrete};
|
||||
use map_model::{AccessRestrictions, CommonEndpoint, PathConstraints, RoadID};
|
||||
use sim::TripMode;
|
||||
use widgetry::mapspace::ToggleZoomed;
|
||||
@ -14,7 +14,7 @@ use widgetry::{
|
||||
|
||||
use crate::app::{App, Transition};
|
||||
use crate::common::RoadSelector;
|
||||
use crate::common::{checkbox_per_mode, intersections_from_roads, CommonState};
|
||||
use crate::common::{checkbox_per_mode, CommonState};
|
||||
use crate::edit::apply_map_edits;
|
||||
|
||||
pub struct ZoneEditor {
|
||||
|
@ -4,7 +4,7 @@ use abstio::Manifest;
|
||||
use abstutil::{prettyprint_bytes, prettyprint_usize, Counter, Timer};
|
||||
use geom::{Distance, Duration, UnitFmt};
|
||||
use map_gui::load::FileLoader;
|
||||
use map_gui::tools::{open_browser, ColorNetwork};
|
||||
use map_gui::tools::{open_browser, percentage_bar, ColorNetwork};
|
||||
use map_gui::ID;
|
||||
use map_model::{PathRequest, PathStepV2, RoadID};
|
||||
use sim::{Scenario, TripEndpoint, TripMode};
|
||||
@ -12,7 +12,6 @@ use widgetry::mapspace::ToggleZoomed;
|
||||
use widgetry::{EventCtx, GfxCtx, Line, Outcome, Panel, Spinner, State, Text, TextExt, Widget};
|
||||
|
||||
use crate::app::{App, Transition};
|
||||
use crate::common::percentage_bar;
|
||||
use crate::ungap::{Layers, Tab, TakeLayers};
|
||||
|
||||
pub struct ShowGaps {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use map_gui::tools::{InputWaypoints, WaypointID};
|
||||
use map_model::RoutingParams;
|
||||
use widgetry::mapspace::{ObjectID, World, WorldOutcome};
|
||||
use widgetry::{
|
||||
@ -6,7 +7,6 @@ use widgetry::{
|
||||
|
||||
use self::results::RouteDetails;
|
||||
use crate::app::{App, Transition};
|
||||
use crate::common::{InputWaypoints, WaypointID};
|
||||
use crate::ungap::{Layers, Tab, TakeLayers};
|
||||
|
||||
mod files;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use geom::{Circle, Distance, Duration, FindClosest, PolyLine, Polygon};
|
||||
use map_gui::tools::PopupMsg;
|
||||
use map_gui::tools::{cmp_dist, cmp_duration, PopupMsg};
|
||||
use map_model::{Path, PathStep, NORMAL_LANE_THICKNESS};
|
||||
use sim::{TripEndpoint, TripMode};
|
||||
use widgetry::mapspace::{ToggleZoomed, ToggleZoomedBuilder};
|
||||
@ -12,7 +12,6 @@ use widgetry::{
|
||||
|
||||
use super::{before_after_button, RoutingPreferences};
|
||||
use crate::app::{App, Transition};
|
||||
use crate::common::{cmp_dist, cmp_duration};
|
||||
|
||||
/// A temporary structure that the caller should unpack and use as needed.
|
||||
pub struct BuiltRoute {
|
||||
|
@ -174,7 +174,7 @@ fn make_world(
|
||||
);
|
||||
}
|
||||
for i in
|
||||
crate::common::intersections_from_roads(&cell.roads.keys().cloned().collect(), map)
|
||||
map_gui::tools::intersections_from_roads(&cell.roads.keys().cloned().collect(), map)
|
||||
{
|
||||
draw.push(color, map.get_i(i).polygon.clone());
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ pub fn run_wasm(root_dom_id: String, assets_base_url: String, assets_are_gzipped
|
||||
run(settings);
|
||||
}
|
||||
|
||||
struct Session {
|
||||
pub struct Session {
|
||||
pub partitioning: Partitioning,
|
||||
pub modal_filters: ModalFilters,
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use geom::{Distance, Duration};
|
||||
use map_gui::tools::{cmp_dist, cmp_duration, InputWaypoints, WaypointID};
|
||||
use map_model::NORMAL_LANE_THICKNESS;
|
||||
use sim::{TripEndpoint, TripMode};
|
||||
use widgetry::mapspace::{ObjectID, ToggleZoomed, World};
|
||||
@ -8,7 +9,6 @@ use widgetry::{
|
||||
|
||||
use super::per_neighborhood::{FilterableObj, Tab};
|
||||
use super::{Neighborhood, NeighborhoodID};
|
||||
use crate::common::{cmp_dist, cmp_duration, InputWaypoints, WaypointID};
|
||||
use crate::{App, Transition};
|
||||
|
||||
pub struct RoutePlanner {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use geom::ArrowCap;
|
||||
use map_gui::tools::ColorNetwork;
|
||||
use map_gui::tools::{percentage_bar, ColorNetwork};
|
||||
use map_model::NORMAL_LANE_THICKNESS;
|
||||
use widgetry::mapspace::{ToggleZoomed, World};
|
||||
use widgetry::{
|
||||
@ -9,7 +9,6 @@ use widgetry::{
|
||||
use super::per_neighborhood::{FilterableObj, Tab};
|
||||
use super::rat_runs::{find_rat_runs, RatRuns};
|
||||
use super::{Neighborhood, NeighborhoodID};
|
||||
use crate::common::percentage_bar;
|
||||
use crate::{App, Transition};
|
||||
|
||||
pub struct BrowseRatRuns {
|
||||
|
@ -1,7 +1,10 @@
|
||||
//! Assorted tools and UI states that're useful for applications built to display maps.
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use abstio::MapName;
|
||||
use geom::Polygon;
|
||||
use map_model::{IntersectionID, Map, RoadID};
|
||||
use widgetry::{lctrl, EventCtx, GfxCtx, Key, Line, Text, Widget};
|
||||
|
||||
pub use self::camera::{CameraState, DefaultMap};
|
||||
@ -14,8 +17,11 @@ pub use self::minimap::{Minimap, MinimapControls};
|
||||
pub use self::navigate::Navigator;
|
||||
pub use self::title_screen::{Executable, TitleScreen};
|
||||
pub use self::turn_explorer::TurnExplorer;
|
||||
pub use self::ui::{ChooseSomething, FilePicker, PopupMsg, PromptInput};
|
||||
pub use self::ui::{
|
||||
cmp_dist, cmp_duration, percentage_bar, ChooseSomething, FilePicker, PopupMsg, PromptInput,
|
||||
};
|
||||
pub use self::url::URLManager;
|
||||
pub use self::waypoints::{InputWaypoints, WaypointID};
|
||||
use crate::AppLike;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@ -41,6 +47,7 @@ mod ui;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod updater;
|
||||
mod url;
|
||||
mod waypoints;
|
||||
|
||||
// Update this ___before___ pushing the commit with "[rebuild] [release]".
|
||||
const NEXT_RELEASE: &str = "0.3.8";
|
||||
@ -374,3 +381,19 @@ pub fn app_header(ctx: &EventCtx, app: &dyn AppLike, title: &str) -> Widget {
|
||||
change_map_btn(ctx, app),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn intersections_from_roads(roads: &BTreeSet<RoadID>, map: &Map) -> BTreeSet<IntersectionID> {
|
||||
let mut results = BTreeSet::new();
|
||||
for r in roads {
|
||||
let r = map.get_r(*r);
|
||||
for i in [r.src_i, r.dst_i] {
|
||||
if results.contains(&i) {
|
||||
continue;
|
||||
}
|
||||
if map.get_i(i).roads.iter().all(|r| roads.contains(r)) {
|
||||
results.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
results
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
//! Generic UI tools. Some of this should perhaps be lifted to widgetry.
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use geom::Polygon;
|
||||
use geom::{Distance, Duration, Polygon};
|
||||
use widgetry::{
|
||||
hotkeys, Choice, Color, DrawBaselayer, EventCtx, GfxCtx, Key, Line, Menu, Outcome, Panel,
|
||||
State, Text, TextBox, Transition, Widget,
|
||||
hotkeys, Choice, Color, DrawBaselayer, EventCtx, GeomBatch, GfxCtx, Key, Line, Menu, Outcome,
|
||||
Panel, State, Text, TextBox, Transition, Widget,
|
||||
};
|
||||
|
||||
use crate::load::FutureLoader;
|
||||
@ -234,3 +236,83 @@ impl FilePicker {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn percentage_bar(ctx: &EventCtx, txt: Text, pct_green: f64) -> Widget {
|
||||
let bad_color = Color::RED;
|
||||
let good_color = Color::GREEN;
|
||||
|
||||
let total_width = 450.0;
|
||||
let height = 32.0;
|
||||
let radius = 4.0;
|
||||
|
||||
let mut batch = GeomBatch::new();
|
||||
// Background
|
||||
batch.push(
|
||||
bad_color,
|
||||
Polygon::rounded_rectangle(total_width, height, radius),
|
||||
);
|
||||
// Foreground
|
||||
if let Some(poly) = Polygon::maybe_rounded_rectangle(pct_green * total_width, height, radius) {
|
||||
batch.push(good_color, poly);
|
||||
}
|
||||
// Text
|
||||
let label = txt.render_autocropped(ctx);
|
||||
let dims = label.get_dims();
|
||||
batch.append(label.translate(10.0, height / 2.0 - dims.height / 2.0));
|
||||
batch.into_widget(ctx)
|
||||
}
|
||||
|
||||
/// Shorter is better
|
||||
pub fn cmp_dist(txt: &mut Text, app: &dyn AppLike, dist: Distance, shorter: &str, longer: &str) {
|
||||
match dist.cmp(&Distance::ZERO) {
|
||||
Ordering::Less => {
|
||||
txt.add_line(
|
||||
Line(format!(
|
||||
"{} {}",
|
||||
(-dist).to_string(&app.opts().units),
|
||||
shorter
|
||||
))
|
||||
.fg(Color::GREEN),
|
||||
);
|
||||
}
|
||||
Ordering::Greater => {
|
||||
txt.add_line(
|
||||
Line(format!("{} {}", dist.to_string(&app.opts().units), longer)).fg(Color::RED),
|
||||
);
|
||||
}
|
||||
Ordering::Equal => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Shorter is better
|
||||
pub fn cmp_duration(
|
||||
txt: &mut Text,
|
||||
app: &dyn AppLike,
|
||||
duration: Duration,
|
||||
shorter: &str,
|
||||
longer: &str,
|
||||
) {
|
||||
match duration.cmp(&Duration::ZERO) {
|
||||
Ordering::Less => {
|
||||
txt.add_line(
|
||||
Line(format!(
|
||||
"{} {}",
|
||||
(-duration).to_string(&app.opts().units),
|
||||
shorter
|
||||
))
|
||||
.fg(Color::GREEN),
|
||||
);
|
||||
}
|
||||
Ordering::Greater => {
|
||||
txt.add_line(
|
||||
Line(format!(
|
||||
"{} {}",
|
||||
duration.to_string(&app.opts().units),
|
||||
longer
|
||||
))
|
||||
.fg(Color::RED),
|
||||
);
|
||||
}
|
||||
Ordering::Equal => {}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use widgetry::{
|
||||
RewriteColor, StackAxis, Text, Widget,
|
||||
};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::AppLike;
|
||||
|
||||
/// Click to add waypoints, drag them, see the list on a panel and delete them. The caller owns the
|
||||
/// Panel and the World, since there's probably more stuff there too.
|
||||
@ -26,8 +26,8 @@ struct Waypoint {
|
||||
}
|
||||
|
||||
impl InputWaypoints {
|
||||
pub fn new(app: &App) -> InputWaypoints {
|
||||
let map = &app.primary.map;
|
||||
pub fn new(app: &dyn AppLike) -> InputWaypoints {
|
||||
let map = app.map();
|
||||
let mut snap_to_endpts = FindClosest::new(map.get_bounds());
|
||||
for i in map.all_intersections() {
|
||||
if i.is_border() {
|
||||
@ -45,7 +45,7 @@ impl InputWaypoints {
|
||||
}
|
||||
|
||||
/// The caller should call `rebuild_world` after this
|
||||
pub fn overwrite(&mut self, app: &App, waypoints: Vec<TripEndpoint>) {
|
||||
pub fn overwrite(&mut self, app: &dyn AppLike, waypoints: Vec<TripEndpoint>) {
|
||||
self.waypoints.clear();
|
||||
for at in waypoints {
|
||||
self.waypoints.push(Waypoint::new(app, at));
|
||||
@ -139,7 +139,7 @@ impl InputWaypoints {
|
||||
/// route and call `get_panel_widget` and `rebuild_world` again.
|
||||
pub fn event(
|
||||
&mut self,
|
||||
app: &mut App,
|
||||
app: &dyn AppLike,
|
||||
panel_outcome: Outcome,
|
||||
world_outcome: WorldOutcome<WaypointID>,
|
||||
) -> bool {
|
||||
@ -239,8 +239,8 @@ impl InputWaypoints {
|
||||
}
|
||||
|
||||
impl Waypoint {
|
||||
fn new(app: &App, at: TripEndpoint) -> Waypoint {
|
||||
let map = &app.primary.map;
|
||||
fn new(app: &dyn AppLike, at: TripEndpoint) -> Waypoint {
|
||||
let map = app.map();
|
||||
let (center, label) = match at {
|
||||
TripEndpoint::Bldg(b) => {
|
||||
let b = map.get_b(b);
|
||||
@ -248,7 +248,10 @@ impl Waypoint {
|
||||
}
|
||||
TripEndpoint::Border(i) => {
|
||||
let i = map.get_i(i);
|
||||
(i.polygon.center(), i.name(app.opts.language.as_ref(), map))
|
||||
(
|
||||
i.polygon.center(),
|
||||
i.name(app.opts().language.as_ref(), map),
|
||||
)
|
||||
}
|
||||
TripEndpoint::SuddenlyAppear(pos) => (pos.pt(map), pos.to_string()),
|
||||
};
|
Loading…
Reference in New Issue
Block a user