start an interactive legend for the minimap. pretty disjoint from real

AgentColorScheme right now
This commit is contained in:
Dustin Carlino 2019-12-16 15:40:32 -08:00
parent a7071a1bc4
commit eda40ecdec
8 changed files with 156 additions and 38 deletions

View File

@ -45,6 +45,8 @@ impl fmt::Display for Color {
} }
impl Color { impl Color {
// TODO Won't this confuse the shader? :P
pub const INVISIBLE: Color = Color::rgba_f(1.0, 0.0, 0.0, 0.0);
pub const BLACK: Color = Color::rgb_f(0.0, 0.0, 0.0); pub const BLACK: Color = Color::rgb_f(0.0, 0.0, 0.0);
pub const WHITE: Color = Color::rgb_f(1.0, 1.0, 1.0); pub const WHITE: Color = Color::rgb_f(1.0, 1.0, 1.0);
pub const RED: Color = Color::rgb_f(1.0, 0.0, 0.0); pub const RED: Color = Color::rgb_f(1.0, 0.0, 0.0);

View File

@ -0,0 +1,3 @@
<svg width="21" height="15" viewBox="0 0 21 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.8" d="M10.5 0.5C5.72727 0.5 1.65136 3.40267 0 7.5C1.65136 11.5973 5.72727 14.5 10.5 14.5C15.2727 14.5 19.3486 11.5973 21 7.5C19.3486 3.40267 15.2727 0.5 10.5 0.5ZM10.5 12.1667C7.86545 12.1667 5.72727 10.076 5.72727 7.5C5.72727 4.924 7.86545 2.83333 10.5 2.83333C13.1345 2.83333 15.2727 4.924 15.2727 7.5C15.2727 10.076 13.1345 12.1667 10.5 12.1667ZM10.5 4.7C8.91545 4.7 7.63636 5.95067 7.63636 7.5C7.63636 9.04933 8.91545 10.3 10.5 10.3C12.0845 10.3 13.3636 9.04933 13.3636 7.5C13.3636 5.95067 12.0845 4.7 10.5 4.7Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 652 B

View File

@ -38,7 +38,6 @@ impl ABTestMode {
(hotkey(Key::D), "diff all trips"), (hotkey(Key::D), "diff all trips"),
(hotkey(Key::A), "stop diffing trips"), (hotkey(Key::A), "stop diffing trips"),
(hotkey(Key::O), "save state"), (hotkey(Key::O), "save state"),
(hotkey(Key::Semicolon), "change agent colorscheme"),
// TODO load arbitrary savestate // TODO load arbitrary savestate
], ],
ctx, ctx,

View File

@ -1,9 +1,9 @@
use crate::common::route_viewer::RouteViewer; use crate::common::route_viewer::RouteViewer;
use crate::common::{RouteExplorer, TripExplorer}; use crate::common::{RouteExplorer, TripExplorer};
use crate::game::{msg, Transition, WizardState}; use crate::game::{msg, Transition};
use crate::render::{AgentColorScheme, MIN_ZOOM_FOR_DETAIL}; use crate::render::MIN_ZOOM_FOR_DETAIL;
use crate::ui::UI; use crate::ui::UI;
use ezgui::{hotkey, Choice, EventCtx, GfxCtx, Key, ModalMenu}; use ezgui::{hotkey, EventCtx, GfxCtx, Key, ModalMenu};
use geom::{Pt2D, Time}; use geom::{Pt2D, Time};
use sim::{TripID, TripResult}; use sim::{TripID, TripResult};
@ -83,29 +83,6 @@ impl AgentTools {
} }
self.route_viewer.event(ctx, ui, menu); self.route_viewer.event(ctx, ui, menu);
if menu.action("change agent colorscheme") {
return Some(Transition::Push(WizardState::new(Box::new(
|wiz, ctx, ui| {
let (_, acs) = wiz.wrap(ctx).choose("Which colorscheme for agents?", || {
let mut choices = Vec::new();
for (acs, name) in AgentColorScheme::all() {
if ui.agent_cs != acs {
choices.push(Choice::new(name, acs));
}
}
choices
})?;
ui.agent_cs = acs;
ui.agent_cs_legend = acs.make_color_legend(ctx, &ui.cs);
ui.primary.draw_map.agents.borrow_mut().invalidate_cache();
if let Some(ref mut s) = ui.secondary {
s.draw_map.agents.borrow_mut().invalidate_cache();
}
Some(Transition::Pop)
},
))));
}
if let Some(explorer) = RouteExplorer::new(ctx, ui) { if let Some(explorer) = RouteExplorer::new(ctx, ui) {
return Some(Transition::Push(Box::new(explorer))); return Some(Transition::Push(Box::new(explorer)));
} }

View File

@ -160,7 +160,6 @@ pub struct ColorLegend {
impl ColorLegend { impl ColorLegend {
pub fn new(ctx: &EventCtx, header: Text, rows: Vec<(&str, Color)>) -> ColorLegend { pub fn new(ctx: &EventCtx, header: Text, rows: Vec<(&str, Color)>) -> ColorLegend {
// TODO add a bg here and stop using prompt?
let mut col = vec![ManagedWidget::draw_text(ctx, header)]; let mut col = vec![ManagedWidget::draw_text(ctx, header)];
let radius = 15.0; let radius = 15.0;

View File

@ -1,18 +1,33 @@
use crate::render::MIN_ZOOM_FOR_DETAIL; use crate::game::{Transition, WizardState};
use crate::managed::{Composite, ManagedWidget, Outcome};
use crate::render::{AgentColorScheme, MIN_ZOOM_FOR_DETAIL};
use crate::ui::UI; use crate::ui::UI;
use ezgui::{Color, EventCtx, GfxCtx, ScreenPt, ScreenRectangle}; use ezgui::{
use geom::{Distance, Polygon, Pt2D, Ring}; hotkey, Button, Choice, Color, EventCtx, GeomBatch, GfxCtx, Key, Line, RewriteColor, ScreenPt,
ScreenRectangle, Text,
};
use geom::{Circle, Distance, Polygon, Pt2D, Ring};
use std::collections::HashMap;
pub struct Minimap { pub struct Minimap {
dragging: bool, dragging: bool,
controls: VisibilityPanel,
} }
impl Minimap { impl Minimap {
pub fn new() -> Minimap { pub fn new(ctx: &EventCtx, ui: &UI) -> Minimap {
Minimap { dragging: false } Minimap {
dragging: false,
controls: VisibilityPanel::new(ctx, ui),
}
}
pub fn event(&mut self, ui: &mut UI, ctx: &mut EventCtx) -> Option<Transition> {
if let Some(t) = self.controls.event(ctx, ui) {
return Some(t);
} }
pub fn event(&mut self, ui: &mut UI, ctx: &mut EventCtx) {
// TODO duplicate some stuff for now, until we figure out what to cache // TODO duplicate some stuff for now, until we figure out what to cache
let square_len = 0.15 * ctx.canvas.window_width; let square_len = 0.15 * ctx.canvas.window_width;
let top_left = ScreenPt::new( let top_left = ScreenPt::new(
@ -38,7 +53,7 @@ impl Minimap {
} else if inner_rect.contains(pt) && ctx.input.left_mouse_button_pressed() { } else if inner_rect.contains(pt) && ctx.input.left_mouse_button_pressed() {
self.dragging = true; self.dragging = true;
} else { } else {
return; return None;
} }
let percent_x = (pt.x - inner_rect.x1) / (inner_rect.x2 - inner_rect.x1); let percent_x = (pt.x - inner_rect.x1) / (inner_rect.x2 - inner_rect.x1);
@ -53,9 +68,13 @@ impl Minimap {
let map_y2 = bounds.min_y + (inner_rect.y2 - inner_rect.y1) / zoom; let map_y2 = bounds.min_y + (inner_rect.y2 - inner_rect.y1) / zoom;
let map_pt = Pt2D::new(map_x, percent_y * (map_y2 - bounds.min_y)); let map_pt = Pt2D::new(map_x, percent_y * (map_y2 - bounds.min_y));
ctx.canvas.center_on_map_pt(map_pt); ctx.canvas.center_on_map_pt(map_pt);
None
} }
pub fn draw(&self, g: &mut GfxCtx, ui: &UI) { pub fn draw(&self, g: &mut GfxCtx, ui: &UI) {
self.controls.draw(g);
if g.canvas.cam_zoom < MIN_ZOOM_FOR_DETAIL { if g.canvas.cam_zoom < MIN_ZOOM_FOR_DETAIL {
return; return;
} }
@ -154,3 +173,116 @@ fn clamp(x: f64, min: f64, max: f64) -> f64 {
x x
} }
} }
pub struct VisibilityPanel {
composite: Composite,
enabled: HashMap<String, bool>,
}
impl VisibilityPanel {
fn make_panel(ctx: &EventCtx, entries: Vec<(String, Color, bool)>) -> Composite {
let radius = 15.0;
let mut col = vec![ManagedWidget::btn_no_cb(Button::text(
Text::from(Line("change")),
Color::INVISIBLE,
Color::ORANGE,
hotkey(Key::Semicolon),
"change agent colorscheme",
ctx,
))];
for (label, color, enabled) in entries {
// TODO Blur out when disabled
col.push(
ManagedWidget::row(vec![
ManagedWidget::btn_no_cb(Button::rectangle_svg(
"assets/tools/visibility.svg",
&format!("show/hide {}", label),
None,
RewriteColor::Change(Color::WHITE, Color::ORANGE),
ctx,
)),
ManagedWidget::draw_batch(
ctx,
GeomBatch::from(vec![(
color,
Circle::new(Pt2D::new(radius, radius), Distance::meters(radius))
.to_polygon(),
)]),
),
ManagedWidget::draw_text(ctx, Text::from(Line(label))),
])
.centered_cross(),
);
}
Composite::minimal_size(
ManagedWidget::col(col).bg(Color::grey(0.4)),
ScreenPt::new(
ctx.canvas.window_width - 550.0,
ctx.canvas.window_height - 300.0,
),
)
}
fn new(ctx: &EventCtx, ui: &UI) -> VisibilityPanel {
// TODO take over make_color_legend
let mut rows = Vec::new();
let mut enabled = HashMap::new();
for (label, color) in vec![
("car", ui.cs.get("unzoomed car")),
("bike", ui.cs.get("unzoomed bike")),
("bus", ui.cs.get("unzoomed bus")),
("pedestrian", ui.cs.get("unzoomed pedestrian")),
] {
enabled.insert(label.to_string(), true);
rows.push((label.to_string(), color, true));
}
VisibilityPanel {
composite: VisibilityPanel::make_panel(ctx, rows),
enabled,
}
}
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
match self.composite.event(ctx, ui) {
Some(Outcome::Transition(_)) => unreachable!(),
Some(Outcome::Clicked(x)) => match x.as_ref() {
"change agent colorscheme" => {
return Some(Transition::Push(WizardState::new(Box::new(
|wiz, ctx, ui| {
let (_, acs) =
wiz.wrap(ctx).choose("Which colorscheme for agents?", || {
let mut choices = Vec::new();
for (acs, name) in AgentColorScheme::all() {
if ui.agent_cs != acs {
choices.push(Choice::new(name, acs));
}
}
choices
})?;
ui.agent_cs = acs;
ui.agent_cs_legend = acs.make_color_legend(ctx, &ui.cs);
ui.primary.draw_map.agents.borrow_mut().invalidate_cache();
if let Some(ref mut s) = ui.secondary {
s.draw_map.agents.borrow_mut().invalidate_cache();
}
Some(Transition::Pop)
},
))));
}
x => {
let key = x["show/hide ".len()..].to_string();
*self.enabled.get_mut(&key).unwrap() = !self.enabled[&key];
println!("{} is now {}", key, self.enabled[&key]);
}
},
None => {}
}
None
}
fn draw(&self, g: &mut GfxCtx) {
self.composite.draw(g);
}
}

View File

@ -80,6 +80,11 @@ impl ManagedWidget {
self self
} }
pub fn centered_cross(mut self) -> ManagedWidget {
self.style.align_items = Some(AlignItems::Center);
self
}
pub fn evenly_spaced(mut self) -> ManagedWidget { pub fn evenly_spaced(mut self) -> ManagedWidget {
self.style.justify_content = Some(JustifyContent::SpaceBetween); self.style.justify_content = Some(JustifyContent::SpaceBetween);
self self

View File

@ -47,7 +47,7 @@ impl SandboxMode {
common: CommonState::new(), common: CommonState::new(),
tool_panel: tool_panel(ctx, Some(Box::new(Overlays::change_overlays))), tool_panel: tool_panel(ctx, Some(Box::new(Overlays::change_overlays))),
minimap: if mode.has_minimap() { minimap: if mode.has_minimap() {
Some(Minimap::new()) Some(Minimap::new(ctx, ui))
} else { } else {
None None
}, },
@ -57,7 +57,6 @@ impl SandboxMode {
vec![ vec![
(lctrl(Key::E), "edit mode"), (lctrl(Key::E), "edit mode"),
(hotkey(Key::Q), "scoreboard"), (hotkey(Key::Q), "scoreboard"),
(hotkey(Key::Semicolon), "change agent colorscheme"),
(None, "explore a bus route"), (None, "explore a bus route"),
], ],
ctx, ctx,
@ -96,7 +95,9 @@ impl State for SandboxMode {
ui.recalculate_current_selection(ctx); ui.recalculate_current_selection(ctx);
} }
if let Some(ref mut m) = self.minimap { if let Some(ref mut m) = self.minimap {
m.event(ui, ctx); if let Some(t) = m.event(ui, ctx) {
return t;
}
} }
if let Some(t) = self.agent_tools.event(ctx, ui, &mut self.menu) { if let Some(t) = self.agent_tools.event(ctx, ui, &mut self.menu) {