mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-29 12:43:38 +03:00
fundamentally different behavior when zoomed in vs not
This commit is contained in:
parent
65307e66f5
commit
f37415bfaa
@ -47,7 +47,7 @@ fn hide_something(ctx: &mut PluginCtx) -> Option<ID> {
|
||||
// No real use case for hiding moving stuff
|
||||
Some(ID::Car(_)) | Some(ID::Pedestrian(_)) | None => None,
|
||||
// Can't hide stuff drawn in a batch
|
||||
Some(ID::Building(_)) | Some(ID::Road(_)) => None,
|
||||
Some(ID::Building(_)) | Some(ID::Road(_)) | Some(ID::Area(_)) | Some(ID::Parcel(_)) => None,
|
||||
Some(id) => {
|
||||
if ctx
|
||||
.input
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::colors::ColorScheme;
|
||||
use crate::objects::{DrawCtx, ID};
|
||||
use crate::render::{DrawCrosswalk, DrawTurn, RenderOptions, Renderable, MIN_ZOOM_FOR_MARKINGS};
|
||||
use crate::render::{DrawCrosswalk, DrawTurn, RenderOptions, Renderable};
|
||||
use ezgui::{Color, Drawable, GfxCtx, Prerender, ScreenPt, Text};
|
||||
use geom::{Bounds, Circle, Distance, Duration, Line, Polygon, Pt2D};
|
||||
use map_model::{
|
||||
@ -86,7 +86,7 @@ impl Renderable for DrawIntersection {
|
||||
if let Some(color) = opts.color {
|
||||
// Don't draw the sidewalk corners
|
||||
g.draw_polygon(color, &self.polygon);
|
||||
} else if g.canvas.cam_zoom >= MIN_ZOOM_FOR_MARKINGS || opts.show_all_detail {
|
||||
} else {
|
||||
g.redraw(&self.draw_default);
|
||||
|
||||
if self.intersection_type == IntersectionType::TrafficSignal {
|
||||
|
@ -1,9 +1,6 @@
|
||||
use crate::colors::ColorScheme;
|
||||
use crate::objects::{DrawCtx, ID};
|
||||
use crate::render::{
|
||||
RenderOptions, Renderable, BIG_ARROW_THICKNESS, MIN_ZOOM_FOR_MARKINGS,
|
||||
PARCEL_BOUNDARY_THICKNESS,
|
||||
};
|
||||
use crate::render::{RenderOptions, Renderable, BIG_ARROW_THICKNESS, PARCEL_BOUNDARY_THICKNESS};
|
||||
use ezgui::{Color, Drawable, GfxCtx, Prerender};
|
||||
use geom::{Bounds, Circle, Distance, Line, Polygon, Pt2D};
|
||||
use map_model::{
|
||||
@ -101,9 +98,7 @@ impl Renderable for DrawLane {
|
||||
g.redraw(&self.draw_default);
|
||||
}
|
||||
|
||||
if g.canvas.cam_zoom >= MIN_ZOOM_FOR_MARKINGS || opts.show_all_detail {
|
||||
g.redraw(&self.draw_markings);
|
||||
}
|
||||
g.redraw(&self.draw_markings);
|
||||
|
||||
if opts.debug_mode {
|
||||
self.draw_debug(g, ctx);
|
||||
|
@ -27,7 +27,6 @@ use ezgui::{Color, GfxCtx, Prerender};
|
||||
use geom::{Bounds, Distance, Pt2D};
|
||||
use map_model::Map;
|
||||
use sim::{DrawCarInput, VehicleType};
|
||||
use std::f64;
|
||||
|
||||
const PARCEL_BOUNDARY_THICKNESS: Distance = Distance::const_meters(0.5);
|
||||
const EXTRA_SHAPE_THICKNESS: Distance = Distance::const_meters(1.0);
|
||||
@ -39,8 +38,6 @@ const TURN_ICON_ARROW_THICKNESS: Distance = Distance::const_meters(0.15);
|
||||
const TURN_ICON_ARROW_LENGTH: Distance = Distance::const_meters(2.0);
|
||||
pub const CROSSWALK_LINE_THICKNESS: Distance = Distance::const_meters(0.25);
|
||||
|
||||
pub const MIN_ZOOM_FOR_MARKINGS: f64 = 1.0;
|
||||
|
||||
// Does something belong here or as a method on ID? If it ONLY applies to renderable things, then
|
||||
// here. For example, trips aren't drawn, so it's meaningless to ask what their bounding box is.
|
||||
pub trait Renderable {
|
||||
@ -60,7 +57,6 @@ pub struct RenderOptions {
|
||||
// TODO This should be accessible through ctx...
|
||||
pub debug_mode: bool,
|
||||
pub is_selected: bool,
|
||||
pub show_all_detail: bool,
|
||||
}
|
||||
|
||||
pub fn draw_vehicle(
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::colors::ColorScheme;
|
||||
use crate::objects::{DrawCtx, ID};
|
||||
use crate::render::{RenderOptions, Renderable, BIG_ARROW_THICKNESS, MIN_ZOOM_FOR_MARKINGS};
|
||||
use crate::render::{RenderOptions, Renderable, BIG_ARROW_THICKNESS};
|
||||
use ezgui::{Color, Drawable, GfxCtx, Prerender};
|
||||
use geom::{Bounds, Polygon, Pt2D};
|
||||
use map_model::{Map, Road, RoadID, LANE_THICKNESS};
|
||||
@ -47,10 +47,10 @@ impl Renderable for DrawRoad {
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, opts: RenderOptions, _ctx: &DrawCtx) {
|
||||
if g.canvas.cam_zoom >= MIN_ZOOM_FOR_MARKINGS || opts.show_all_detail {
|
||||
g.redraw(&self.draw_center_line);
|
||||
} else if let Some(color) = opts.color {
|
||||
if let Some(color) = opts.color {
|
||||
g.draw_polygon(color, &self.polygon);
|
||||
} else {
|
||||
g.redraw(&self.draw_center_line);
|
||||
}
|
||||
}
|
||||
|
||||
|
182
editor/src/ui.rs
182
editor/src/ui.rs
@ -1,7 +1,5 @@
|
||||
use crate::objects::{DrawCtx, RenderingHints, ID};
|
||||
use crate::render::{
|
||||
draw_vehicle, AgentCache, DrawPedestrian, RenderOptions, Renderable, MIN_ZOOM_FOR_MARKINGS,
|
||||
};
|
||||
use crate::render::{draw_vehicle, AgentCache, DrawPedestrian, RenderOptions, Renderable};
|
||||
use crate::state::UIState;
|
||||
use abstutil;
|
||||
use ezgui::{
|
||||
@ -15,6 +13,8 @@ use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
use std::process;
|
||||
|
||||
const MIN_ZOOM_FOR_DETAIL: f64 = 1.0;
|
||||
|
||||
pub struct UI<S: UIState> {
|
||||
state: S,
|
||||
}
|
||||
@ -243,26 +243,6 @@ impl<S: UIState> GUI<RenderingHints> for UI<S> {
|
||||
fn new_draw(&self, g: &mut GfxCtx, hints: &RenderingHints, screencap: bool) -> Option<String> {
|
||||
let state = self.state.get_state();
|
||||
|
||||
// TODO Not quite ready yet
|
||||
if false {
|
||||
g.clear(state.cs.get_def("true background", Color::BLACK));
|
||||
g.redraw(&state.primary.draw_map.boundary_polygon);
|
||||
} else {
|
||||
g.clear(state.cs.get("map background"));
|
||||
}
|
||||
|
||||
let mut cache = state.primary.draw_map.agents.borrow_mut();
|
||||
let objects = self.get_renderables_back_to_front(
|
||||
g.get_screen_bounds(),
|
||||
if screencap {
|
||||
None
|
||||
} else {
|
||||
Some(g.canvas.cam_zoom)
|
||||
},
|
||||
&g.prerender,
|
||||
&mut cache,
|
||||
);
|
||||
|
||||
let ctx = DrawCtx {
|
||||
cs: &state.cs,
|
||||
map: &state.primary.map,
|
||||
@ -272,62 +252,73 @@ impl<S: UIState> GUI<RenderingHints> for UI<S> {
|
||||
};
|
||||
let mut sample_intersection: Option<String> = None;
|
||||
|
||||
let mut drawn_all_thick_roads = false;
|
||||
let mut drawn_all_unzoomed_intersections = false;
|
||||
let mut drawn_all_buildings = false;
|
||||
let mut drawn_all_areas = false;
|
||||
let mut drawn_all_parcels = false;
|
||||
// TODO Not quite ready yet
|
||||
if false {
|
||||
g.clear(state.cs.get_def("true background", Color::BLACK));
|
||||
g.redraw(&state.primary.draw_map.boundary_polygon);
|
||||
} else {
|
||||
g.clear(state.cs.get("map background"));
|
||||
}
|
||||
|
||||
for obj in objects {
|
||||
match obj.get_id() {
|
||||
ID::Building(_) => {
|
||||
if !drawn_all_buildings {
|
||||
g.redraw(&state.primary.draw_map.draw_all_buildings);
|
||||
drawn_all_buildings = true;
|
||||
}
|
||||
}
|
||||
ID::Area(_) => {
|
||||
if !drawn_all_areas {
|
||||
g.redraw(&state.primary.draw_map.draw_all_areas);
|
||||
drawn_all_areas = true;
|
||||
}
|
||||
}
|
||||
ID::Parcel(_) => {
|
||||
if !drawn_all_parcels {
|
||||
g.redraw(&state.primary.draw_map.draw_all_parcels);
|
||||
drawn_all_parcels = true;
|
||||
}
|
||||
}
|
||||
ID::Road(_) => {
|
||||
if !drawn_all_thick_roads {
|
||||
if g.canvas.cam_zoom < MIN_ZOOM_FOR_MARKINGS {
|
||||
g.redraw(&state.primary.draw_map.draw_all_thick_roads);
|
||||
}
|
||||
drawn_all_thick_roads = true;
|
||||
}
|
||||
}
|
||||
ID::Intersection(_) => {
|
||||
if !drawn_all_unzoomed_intersections {
|
||||
if g.canvas.cam_zoom < MIN_ZOOM_FOR_MARKINGS {
|
||||
g.redraw(&state.primary.draw_map.draw_all_unzoomed_intersections);
|
||||
}
|
||||
drawn_all_unzoomed_intersections = true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
let opts = RenderOptions {
|
||||
color: state.color_obj(obj.get_id(), &ctx),
|
||||
debug_mode: state.layers.debug_mode,
|
||||
is_selected: state.primary.current_selection == Some(obj.get_id()),
|
||||
// TODO If a ToggleableLayer is currently off, this won't affect it!
|
||||
show_all_detail: screencap,
|
||||
};
|
||||
obj.draw(g, opts, &ctx);
|
||||
if g.canvas.cam_zoom < MIN_ZOOM_FOR_DETAIL && !screencap {
|
||||
// Unzoomed mode
|
||||
if state.layers.show_areas {
|
||||
g.redraw(&state.primary.draw_map.draw_all_areas);
|
||||
}
|
||||
if state.layers.show_parcels {
|
||||
g.redraw(&state.primary.draw_map.draw_all_parcels);
|
||||
}
|
||||
if state.layers.show_lanes {
|
||||
g.redraw(&state.primary.draw_map.draw_all_thick_roads);
|
||||
}
|
||||
if state.layers.show_intersections {
|
||||
g.redraw(&state.primary.draw_map.draw_all_unzoomed_intersections);
|
||||
}
|
||||
if state.layers.show_buildings {
|
||||
g.redraw(&state.primary.draw_map.draw_all_buildings);
|
||||
}
|
||||
} else {
|
||||
let mut cache = state.primary.draw_map.agents.borrow_mut();
|
||||
let objects =
|
||||
self.get_renderables_back_to_front(g.get_screen_bounds(), &g.prerender, &mut cache);
|
||||
|
||||
if screencap && sample_intersection.is_none() {
|
||||
if let ID::Intersection(id) = obj.get_id() {
|
||||
sample_intersection = Some(format!("_i{}", id.0));
|
||||
let mut drawn_all_buildings = false;
|
||||
let mut drawn_all_areas = false;
|
||||
let mut drawn_all_parcels = false;
|
||||
|
||||
for obj in objects {
|
||||
match obj.get_id() {
|
||||
ID::Building(_) => {
|
||||
if !drawn_all_buildings {
|
||||
g.redraw(&state.primary.draw_map.draw_all_buildings);
|
||||
drawn_all_buildings = true;
|
||||
}
|
||||
}
|
||||
ID::Area(_) => {
|
||||
if !drawn_all_areas {
|
||||
g.redraw(&state.primary.draw_map.draw_all_areas);
|
||||
drawn_all_areas = true;
|
||||
}
|
||||
}
|
||||
ID::Parcel(_) => {
|
||||
if !drawn_all_parcels {
|
||||
g.redraw(&state.primary.draw_map.draw_all_parcels);
|
||||
drawn_all_parcels = true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
let opts = RenderOptions {
|
||||
color: state.color_obj(obj.get_id(), &ctx),
|
||||
debug_mode: state.layers.debug_mode,
|
||||
is_selected: state.primary.current_selection == Some(obj.get_id()),
|
||||
};
|
||||
obj.draw(g, opts, &ctx);
|
||||
|
||||
if screencap && sample_intersection.is_none() {
|
||||
if let ID::Intersection(id) = obj.get_id() {
|
||||
sample_intersection = Some(format!("_i{}", id.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -406,12 +397,16 @@ impl<S: UIState> UI<S> {
|
||||
}
|
||||
|
||||
fn mouseover_something(&self, ctx: &EventCtx) -> Option<ID> {
|
||||
// Unzoomed mode
|
||||
if ctx.canvas.cam_zoom < MIN_ZOOM_FOR_DETAIL {
|
||||
return None;
|
||||
}
|
||||
|
||||
let pt = ctx.canvas.get_cursor_in_map_space()?;
|
||||
|
||||
let mut cache = self.state.get_state().primary.draw_map.agents.borrow_mut();
|
||||
let mut objects = self.get_renderables_back_to_front(
|
||||
Circle::new(pt, Distance::meters(3.0)).get_bounds(),
|
||||
Some(ctx.canvas.cam_zoom),
|
||||
ctx.prerender,
|
||||
&mut cache,
|
||||
);
|
||||
@ -424,7 +419,8 @@ impl<S: UIState> UI<S> {
|
||||
match obj.get_id() {
|
||||
ID::Parcel(_) => {}
|
||||
ID::Area(_) => {}
|
||||
ID::Road(_) if ctx.canvas.cam_zoom >= MIN_ZOOM_FOR_MARKINGS => {}
|
||||
// Thick roads are only shown when unzoomed, when we don't mouseover at all.
|
||||
ID::Road(_) => {}
|
||||
_ => {
|
||||
if obj.contains_pt(pt, &self.state.get_state().primary.map) {
|
||||
return Some(obj.get_id());
|
||||
@ -452,7 +448,6 @@ impl<S: UIState> UI<S> {
|
||||
fn get_renderables_back_to_front<'a>(
|
||||
&'a self,
|
||||
bounds: Bounds,
|
||||
zoom: Option<f64>,
|
||||
prerender: &Prerender,
|
||||
agents: &'a mut AgentCache,
|
||||
) -> Vec<Box<&'a Renderable>> {
|
||||
@ -460,12 +455,6 @@ impl<S: UIState> UI<S> {
|
||||
let map = &state.primary.map;
|
||||
let draw_map = &state.primary.draw_map;
|
||||
|
||||
let show_stuff_on_lanes = if let Some(z) = zoom {
|
||||
z >= MIN_ZOOM_FOR_MARKINGS
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
let mut parcels: Vec<Box<&Renderable>> = Vec::new();
|
||||
let mut areas: Vec<Box<&Renderable>> = Vec::new();
|
||||
let mut lanes: Vec<Box<&Renderable>> = Vec::new();
|
||||
@ -485,15 +474,13 @@ impl<S: UIState> UI<S> {
|
||||
ID::Parcel(id) => parcels.push(Box::new(draw_map.get_p(id))),
|
||||
ID::Area(id) => areas.push(Box::new(draw_map.get_a(id))),
|
||||
ID::Lane(id) => {
|
||||
if show_stuff_on_lanes {
|
||||
lanes.push(Box::new(draw_map.get_l(id)));
|
||||
let lane = map.get_l(id);
|
||||
if !state.show_icons_for(lane.dst_i) {
|
||||
agents_on.push(Traversable::Lane(id));
|
||||
}
|
||||
for bs in &lane.bus_stops {
|
||||
bus_stops.push(Box::new(draw_map.get_bs(*bs)));
|
||||
}
|
||||
lanes.push(Box::new(draw_map.get_l(id)));
|
||||
let lane = map.get_l(id);
|
||||
if !state.show_icons_for(lane.dst_i) {
|
||||
agents_on.push(Traversable::Lane(id));
|
||||
}
|
||||
for bs in &lane.bus_stops {
|
||||
bus_stops.push(Box::new(draw_map.get_bs(*bs)));
|
||||
}
|
||||
}
|
||||
ID::Road(id) => {
|
||||
@ -505,10 +492,7 @@ impl<S: UIState> UI<S> {
|
||||
if state.show_icons_for(id) {
|
||||
turn_icons.push(Box::new(draw_map.get_t(*t)));
|
||||
} else {
|
||||
// For consistency, don't draw agents doing a turn when zoomed out
|
||||
if show_stuff_on_lanes {
|
||||
agents_on.push(Traversable::Turn(*t));
|
||||
}
|
||||
agents_on.push(Traversable::Turn(*t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user