using color scheme in most places

This commit is contained in:
Dustin Carlino 2018-06-21 10:03:51 -07:00
parent 623f0528cd
commit e7e334a460
10 changed files with 234 additions and 243 deletions

View File

@ -1,135 +1,135 @@
{ {
"map": { "map": {
"Sidewalk": [
0.7231658,
0.68797094,
0.75104135,
1.0
],
"TurnIconCircle": [
0.063196,
0.79656935,
0.62435865,
1.0
],
"Turn": [
0.7646927,
0.08863717,
0.598167,
1.0
],
"NextQueued": [
0.13027889,
0.48449433,
0.9080713,
1.0
],
"TurnIconInactive": [
0.14615297,
0.9214722,
0.4148339,
1.0
],
"RoadOrientation": [
0.7582534,
0.99075705,
0.70908225,
1.0
],
"Queued": [
0.3389185,
0.0877803,
0.9954711,
1.0
],
"ConflictingTurn": [
0.2613939,
0.05315745,
0.13176817,
1.0
],
"ChangedStopSignIntersection": [
0.68394506,
0.3545285,
0.798195,
1.0
],
"ParcelInterior": [
0.61576617,
0.3485126,
0.079839945,
1.0
],
"Building": [
0.6194557,
0.04746574,
0.048986018,
1.0
],
"ParcelBoundary": [
0.10262495,
0.27895468,
0.24475342,
1.0
],
"Parking": [
0.18110627,
0.7668609,
0.78273845,
1.0
],
"Selected": [
0.5561179,
0.67208916,
0.888709,
1.0
],
"Road": [
0.42062867,
0.18196481,
0.002040863,
1.0
],
"SearchResult": [
0.29739696,
0.1459617,
0.38928866,
1.0
],
"Debug": [ "Debug": [
0.52514017, 1.0,
0.4302144, 0.0,
0.9794487, 0.0,
1.0
],
"ChangedTrafficSignalIntersection": [
0.92895883,
0.54622823,
0.5924938,
1.0
],
"NormalIntersection": [
0.6803359,
0.82401633,
0.27655125,
1.0
],
"TrafficSignalIntersection": [
0.53518486,
0.6754812,
0.6970498,
1.0 1.0
], ],
"BrightDebug": [ "BrightDebug": [
0.51087564, 0.8,
0.66038465, 0.1,
0.94535834, 0.1,
1.0
],
"Road": [
0.0,
0.0,
0.0,
1.0
],
"Parking": [
0.5,
0.0,
0.5,
1.0
],
"Sidewalk": [
0.0,
1.0,
0.0,
1.0
],
"ChangedStopSignIntersection": [
0.0,
1.0,
0.0,
1.0
],
"ChangedTrafficSignalIntersection": [
1.0,
0.65,
0.0,
1.0
],
"TrafficSignalIntersection": [
1.0,
1.0,
0.0,
1.0
],
"NormalIntersection": [
0.3,
0.3,
0.3,
1.0
],
"Selected": [
0.0,
0.0,
1.0,
1.0
],
"Turn": [
1.0,
0.0,
0.0,
1.0
],
"ConflictingTurn": [
1.0,
0.0,
0.0,
0.5
],
"Building": [
0.7,
0.7,
0.7,
1.0
],
"ParcelBoundary": [
0.3,
0.3,
0.3,
1.0
],
"ParcelInterior": [
0.5,
0.0,
0.0,
1.0
],
"RoadOrientation": [
1.0,
1.0,
0.0,
1.0
],
"SearchResult": [
1.0,
0.0,
0.0,
1.0 1.0
], ],
"Visited": [ "Visited": [
0.6067979, 0.0,
0.99225366, 0.0,
0.9826904, 1.0,
1.0
],
"Queued": [
1.0,
0.0,
0.0,
1.0
],
"NextQueued": [
0.0,
1.0,
0.0,
1.0
],
"TurnIconCircle": [
0.3,
0.3,
0.3,
1.0
],
"TurnIconInactive": [
0.7,
0.7,
0.7,
1.0 1.0
] ]
} }

View File

@ -4,13 +4,13 @@ extern crate serde_json;
use graphics::types::Color; use graphics::types::Color;
use rand; use rand;
use std::collections::HashMap; use std::collections::BTreeMap;
use std::fs::File; use std::fs::File;
use std::io::{Error, ErrorKind, Read, Write}; use std::io::{Error, ErrorKind, Read, Write};
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, EnumIter, Hash)] #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, EnumIter, PartialOrd, Ord)]
pub enum ColorSetting { pub enum Colors {
Debug, Debug,
BrightDebug, BrightDebug,
Road, Road,
@ -37,7 +37,7 @@ pub enum ColorSetting {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct ColorScheme { pub struct ColorScheme {
map: HashMap<ColorSetting, Color>, map: BTreeMap<Colors, Color>,
} }
impl ColorScheme { impl ColorScheme {
@ -53,11 +53,11 @@ impl ColorScheme {
file.read_to_string(&mut contents)?; file.read_to_string(&mut contents)?;
let scheme: ColorScheme = serde_json::from_str(&contents).unwrap(); let scheme: ColorScheme = serde_json::from_str(&contents).unwrap();
for setting in ColorSetting::iter() { for color in Colors::iter() {
if !scheme.map.contains_key(&setting) { if !scheme.map.contains_key(&color) {
return Err(Error::new( return Err(Error::new(
ErrorKind::Other, ErrorKind::Other,
format!("no color for {:?} defined", setting), format!("no color for {:?} defined", color),
)); ));
} }
} }
@ -65,16 +65,20 @@ impl ColorScheme {
Ok(scheme) Ok(scheme)
} }
pub fn random_settings() -> ColorScheme { pub fn random_colors() -> ColorScheme {
let mut scheme = ColorScheme { let mut scheme = ColorScheme {
map: HashMap::new(), map: BTreeMap::new(),
}; };
for setting in ColorSetting::iter() { for color in Colors::iter() {
scheme.map.insert( scheme
setting, .map
[rand::random(), rand::random(), rand::random(), 1.0], .insert(color, [rand::random(), rand::random(), rand::random(), 1.0]);
);
} }
scheme scheme
} }
pub fn get(&self, c: Colors) -> Color {
// TODO make sure this isn't slow; maybe back this with an array
*self.map.get(&c).unwrap()
}
} }

View File

@ -2,11 +2,11 @@
extern crate map_model; extern crate map_model;
use colors::{ColorScheme, Colors};
use ezgui::input::UserInput; use ezgui::input::UserInput;
use graphics::types::Color; use graphics::types::Color;
use map_model::{Map, Road, RoadID}; use map_model::{Map, Road, RoadID};
use piston::input::Key; use piston::input::Key;
use render;
use std::collections::{HashSet, VecDeque}; use std::collections::{HashSet, VecDeque};
// Keeps track of state so this can be interactively visualized // Keeps track of state so this can be interactively visualized
@ -76,16 +76,16 @@ impl Floodfiller {
false false
} }
pub fn color_r(&self, r: &Road) -> Option<Color> { pub fn color_r(&self, r: &Road, cs: &ColorScheme) -> Option<Color> {
if self.visited.contains(&r.id) { if self.visited.contains(&r.id) {
return Some(render::VISITED_COLOR); return Some(cs.get(Colors::Visited));
} }
if !self.queue.is_empty() && *self.queue.front().unwrap() == r.id { if !self.queue.is_empty() && *self.queue.front().unwrap() == r.id {
return Some(render::NEXT_QUEUED_COLOR); return Some(cs.get(Colors::NextQueued));
} }
// TODO linear search shouldnt suck too much for interactive mode // TODO linear search shouldnt suck too much for interactive mode
if self.queue.contains(&r.id) { if self.queue.contains(&r.id) {
return Some(render::QUEUED_COLOR); return Some(cs.get(Colors::Queued));
} }
None None
} }

View File

@ -1,11 +1,11 @@
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0 // Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
use colors::{ColorScheme, Colors};
use ezgui::input::UserInput; use ezgui::input::UserInput;
use ezgui::text_box::TextBox; use ezgui::text_box::TextBox;
use graphics::types::Color; use graphics::types::Color;
use map_model; use map_model;
use piston::input::Key; use piston::input::Key;
use render;
pub enum SearchState { pub enum SearchState {
Empty, Empty,
@ -14,18 +14,18 @@ pub enum SearchState {
} }
impl SearchState { impl SearchState {
pub fn color_r(&self, r: &map_model::Road) -> Option<Color> { pub fn color_r(&self, r: &map_model::Road, cs: &ColorScheme) -> Option<Color> {
self.choose_color(&r.osm_tags) self.choose_color(&r.osm_tags, cs)
} }
pub fn color_b(&self, b: &map_model::Building) -> Option<Color> { pub fn color_b(&self, b: &map_model::Building, cs: &ColorScheme) -> Option<Color> {
self.choose_color(&b.osm_tags) self.choose_color(&b.osm_tags, cs)
} }
fn choose_color(&self, osm_tags: &[String]) -> Option<Color> { fn choose_color(&self, osm_tags: &[String], cs: &ColorScheme) -> Option<Color> {
if let SearchState::FilterOSM(filter) = self { if let SearchState::FilterOSM(filter) = self {
for tag in osm_tags { for tag in osm_tags {
if tag.contains(filter) { if tag.contains(filter) {
return Some(render::SEARCH_RESULT_COLOR); return Some(cs.get(Colors::SearchResult));
} }
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0 // Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
use animation; use animation;
use colors::{ColorScheme, Colors};
use control::ControlMap; use control::ControlMap;
use ezgui::canvas::{Canvas, GfxCtx}; use ezgui::canvas::{Canvas, GfxCtx};
use ezgui::input::UserInput; use ezgui::input::UserInput;
@ -139,6 +140,7 @@ impl SelectionState {
draw_map: &render::DrawMap, draw_map: &render::DrawMap,
control_map: &ControlMap, control_map: &ControlMap,
sim: &Sim, sim: &Sim,
cs: &ColorScheme,
g: &mut GfxCtx, g: &mut GfxCtx,
) { ) {
match *self { match *self {
@ -147,7 +149,7 @@ impl SelectionState {
if let Some(signal) = control_map.traffic_signals.get(&id) { if let Some(signal) = control_map.traffic_signals.get(&id) {
let (cycle, _) = signal.current_cycle_and_remaining_time(sim.time.as_time()); let (cycle, _) = signal.current_cycle_and_remaining_time(sim.time.as_time());
for t in &cycle.turns { for t in &cycle.turns {
draw_map.get_t(*t).draw_full(g, render::TURN_COLOR); draw_map.get_t(*t).draw_full(g, cs.get(Colors::Turn));
} }
} }
} }
@ -160,22 +162,22 @@ impl SelectionState {
let turn = draw_map.get_t(relevant_turns[idx % relevant_turns.len()].id); let turn = draw_map.get_t(relevant_turns[idx % relevant_turns.len()].id);
let geom_turn = let geom_turn =
geom_map.get_t(relevant_turns[idx % relevant_turns.len()].id); geom_map.get_t(relevant_turns[idx % relevant_turns.len()].id);
turn.draw_full(g, render::TURN_COLOR); turn.draw_full(g, cs.get(Colors::Turn));
for map_t in all_turns { for map_t in all_turns {
let draw_t = draw_map.get_t(map_t.id); let draw_t = draw_map.get_t(map_t.id);
let geom_t = geom_map.get_t(map_t.id); let geom_t = geom_map.get_t(map_t.id);
if geom_t.conflicts_with(geom_turn) { if geom_t.conflicts_with(geom_turn) {
// TODO should we instead change color_t? // TODO should we instead change color_t?
draw_t.draw_icon(g, render::CONFLICTING_TURN_COLOR); draw_t.draw_icon(g, cs.get(Colors::ConflictingTurn), cs);
} }
} }
} }
None => for turn in &relevant_turns { None => for turn in &relevant_turns {
draw_map.get_t(turn.id).draw_full(g, render::TURN_COLOR); draw_map.get_t(turn.id).draw_full(g, cs.get(Colors::Turn));
}, },
} }
// TODO tmp // TODO tmp
draw_map.get_r(id).draw_debug(g, geom_map.get_r(id)); draw_map.get_r(id).draw_debug(g, cs, geom_map.get_r(id));
} }
SelectionState::TooltipRoad(id) => { SelectionState::TooltipRoad(id) => {
canvas.draw_mouse_tooltip(g, &draw_map.get_r(id).tooltip_lines(map, geom_map)); canvas.draw_mouse_tooltip(g, &draw_map.get_r(id).tooltip_lines(map, geom_map));
@ -192,34 +194,36 @@ impl SelectionState {
// TODO instead, since color logic is complicated anyway, just have a way to ask "are we // TODO instead, since color logic is complicated anyway, just have a way to ask "are we
// selecting this generic ID?" // selecting this generic ID?"
pub fn color_r(&self, r: &map_model::Road) -> Option<Color> { pub fn color_r(&self, r: &map_model::Road, cs: &ColorScheme) -> Option<Color> {
match *self { match *self {
SelectionState::SelectedRoad(id, _) if r.id == id => Some(render::SELECTED_COLOR), SelectionState::SelectedRoad(id, _) if r.id == id => Some(cs.get(Colors::Selected)),
SelectionState::TooltipRoad(id) if r.id == id => Some(render::SELECTED_COLOR), SelectionState::TooltipRoad(id) if r.id == id => Some(cs.get(Colors::Selected)),
_ => None, _ => None,
} }
} }
pub fn color_i(&self, i: &map_model::Intersection) -> Option<Color> { pub fn color_i(&self, i: &map_model::Intersection, cs: &ColorScheme) -> Option<Color> {
match *self { match *self {
SelectionState::SelectedIntersection(id) if i.id == id => Some(render::SELECTED_COLOR), SelectionState::SelectedIntersection(id) if i.id == id => {
Some(cs.get(Colors::Selected))
}
_ => None, _ => None,
} }
} }
pub fn color_t(&self, t: &map_model::Turn) -> Option<Color> { pub fn color_t(&self, t: &map_model::Turn, cs: &ColorScheme) -> Option<Color> {
match *self { match *self {
SelectionState::SelectedTurn(id) if t.id == id => Some(render::SELECTED_COLOR), SelectionState::SelectedTurn(id) if t.id == id => Some(cs.get(Colors::Selected)),
_ => None, _ => None,
} }
} }
pub fn color_b(&self, b: &map_model::Building) -> Option<Color> { pub fn color_b(&self, b: &map_model::Building, cs: &ColorScheme) -> Option<Color> {
match *self { match *self {
SelectionState::SelectedBuilding(id) if b.id == id => Some(render::SELECTED_COLOR), SelectionState::SelectedBuilding(id) if b.id == id => Some(cs.get(Colors::Selected)),
_ => None, _ => None,
} }
} }
pub fn color_c(&self, c: CarID) -> Option<Color> { pub fn color_c(&self, c: CarID, cs: &ColorScheme) -> Option<Color> {
match *self { match *self {
SelectionState::SelectedCar(id) if c == id => Some(render::SELECTED_COLOR), SelectionState::SelectedCar(id) if c == id => Some(cs.get(Colors::Selected)),
_ => None, _ => None,
} }
} }

View File

@ -9,9 +9,7 @@ mod parcel;
mod road; mod road;
mod turn; mod turn;
use ezgui::canvas;
use geom; use geom;
use graphics::types::Color;
pub use render::map::DrawMap; pub use render::map::DrawMap;
pub use render::road::DrawRoad; pub use render::road::DrawRoad;
pub use render::turn::DrawTurn; pub use render::turn::DrawTurn;
@ -24,27 +22,3 @@ const TURN_ICON_ARROW_THICKNESS: f64 = geom::BIG_ARROW_THICKNESS / 3.0;
const BIG_ARROW_TIP_LENGTH: f64 = 1.0; const BIG_ARROW_TIP_LENGTH: f64 = 1.0;
const TURN_ICON_ARROW_TIP_LENGTH: f64 = BIG_ARROW_TIP_LENGTH * 0.8; const TURN_ICON_ARROW_TIP_LENGTH: f64 = BIG_ARROW_TIP_LENGTH * 0.8;
const TURN_ICON_ARROW_LENGTH: f64 = 2.0; const TURN_ICON_ARROW_LENGTH: f64 = 2.0;
pub const DEBUG_COLOR: Color = canvas::RED;
pub const BRIGHT_DEBUG_COLOR: Color = [0.8, 0.1, 0.1, 1.0];
pub const ROAD_COLOR: Color = canvas::BLACK;
pub const PARKING_COLOR: Color = canvas::PURPLE;
pub const SIDEWALK_COLOR: Color = canvas::GREEN;
pub const CHANGED_STOP_SIGN_INTERSECTION_COLOR: Color = canvas::GREEN;
pub const CHANGED_TRAFFIC_SIGNAL_INTERSECTION_COLOR: Color = canvas::ORANGE;
pub const TRAFFIC_SIGNAL_INTERSECTION_COLOR: Color = canvas::YELLOW;
pub const NORMAL_INTERSECTION_COLOR: Color = canvas::DARK_GREY;
pub const SELECTED_COLOR: Color = canvas::BLUE;
pub const TURN_COLOR: Color = canvas::GREEN;
pub const CONFLICTING_TURN_COLOR: Color = [1.0, 0.0, 0.0, 0.5];
pub const BUILDING_COLOR: Color = canvas::LIGHT_GREY;
pub const PARCEL_BOUNDARY_COLOR: Color = canvas::DARK_GREY;
pub const PARCEL_INTERIOR_COLOR: Color = canvas::LIGHT_BROWN;
const ROAD_ORIENTATION_COLOR: Color = canvas::YELLOW;
pub const SEARCH_RESULT_COLOR: Color = canvas::RED;
// For interactive algorithms
pub const VISITED_COLOR: Color = canvas::BLUE;
pub const QUEUED_COLOR: Color = canvas::RED;
pub const NEXT_QUEUED_COLOR: Color = canvas::GREEN;
const TURN_ICON_CIRCLE_COLOR: Color = canvas::DARK_GREY;
pub const TURN_ICON_INACTIVE_COLOR: Color = canvas::LIGHT_GREY;

View File

@ -4,6 +4,7 @@ extern crate aabb_quadtree;
extern crate map_model; extern crate map_model;
use aabb_quadtree::geom::Rect; use aabb_quadtree::geom::Rect;
use colors::{ColorScheme, Colors};
use ezgui::canvas::GfxCtx; use ezgui::canvas::GfxCtx;
use geom; use geom;
use geom::geometry; use geom::geometry;
@ -11,7 +12,7 @@ use graphics;
use graphics::math::Vec2d; use graphics::math::Vec2d;
use graphics::types::Color; use graphics::types::Color;
use map_model::{Pt2D, RoadID}; use map_model::{Pt2D, RoadID};
use render::{BRIGHT_DEBUG_COLOR, DEBUG_COLOR, PARCEL_BOUNDARY_THICKNESS, ROAD_ORIENTATION_COLOR}; use render::PARCEL_BOUNDARY_THICKNESS;
use std::f64; use std::f64;
#[derive(Debug)] #[derive(Debug)]
@ -47,9 +48,9 @@ impl DrawRoad {
} }
} }
pub fn draw_detail(&self, g: &mut GfxCtx) { pub fn draw_detail(&self, g: &mut GfxCtx, cs: &ColorScheme) {
let road_marking = let road_marking =
graphics::Line::new_round(ROAD_ORIENTATION_COLOR, geom::BIG_ARROW_THICKNESS); graphics::Line::new_round(cs.get(Colors::RoadOrientation), geom::BIG_ARROW_THICKNESS);
for pair in self.yellow_center_lines.windows(2) { for pair in self.yellow_center_lines.windows(2) {
road_marking.draw( road_marking.draw(
@ -61,9 +62,10 @@ impl DrawRoad {
} }
} }
pub fn draw_debug(&self, g: &mut GfxCtx, geom_r: &geom::GeomRoad) { pub fn draw_debug(&self, g: &mut GfxCtx, cs: &ColorScheme, geom_r: &geom::GeomRoad) {
let line = graphics::Line::new_round(DEBUG_COLOR, PARCEL_BOUNDARY_THICKNESS / 2.0); let line =
let circle = graphics::Ellipse::new(BRIGHT_DEBUG_COLOR); graphics::Line::new_round(cs.get(Colors::Debug), PARCEL_BOUNDARY_THICKNESS / 2.0);
let circle = graphics::Ellipse::new(cs.get(Colors::BrightDebug));
for &(pt1, pt2) in &geom_r.lane_center_lines { for &(pt1, pt2) in &geom_r.lane_center_lines {
line.draw( line.draw(

View File

@ -4,6 +4,7 @@ extern crate aabb_quadtree;
extern crate map_model; extern crate map_model;
use aabb_quadtree::geom::Rect; use aabb_quadtree::geom::Rect;
use colors::{ColorScheme, Colors};
use ezgui::canvas::GfxCtx; use ezgui::canvas::GfxCtx;
use geom; use geom;
use geom::GeomMap; use geom::GeomMap;
@ -13,7 +14,7 @@ use graphics::math::Vec2d;
use graphics::types::Color; use graphics::types::Color;
use map_model::TurnID; use map_model::TurnID;
use render::{BIG_ARROW_TIP_LENGTH, TURN_ICON_ARROW_LENGTH, TURN_ICON_ARROW_THICKNESS, use render::{BIG_ARROW_TIP_LENGTH, TURN_ICON_ARROW_LENGTH, TURN_ICON_ARROW_THICKNESS,
TURN_ICON_ARROW_TIP_LENGTH, TURN_ICON_CIRCLE_COLOR}; TURN_ICON_ARROW_TIP_LENGTH};
use std::f64; use std::f64;
use vecmath; use vecmath;
@ -78,8 +79,8 @@ impl DrawTurn {
); );
} }
pub fn draw_icon(&self, g: &mut GfxCtx, color: Color) { pub fn draw_icon(&self, g: &mut GfxCtx, color: Color, cs: &ColorScheme) {
let circle = graphics::Ellipse::new(TURN_ICON_CIRCLE_COLOR); let circle = graphics::Ellipse::new(cs.get(Colors::TurnIconCircle));
circle.draw(self.icon_circle, &g.ctx.draw_state, g.ctx.transform, g.gfx); circle.draw(self.icon_circle, &g.ctx.draw_state, g.ctx.transform, g.gfx);
let turn_line = graphics::Line::new_round(color, TURN_ICON_ARROW_THICKNESS); let turn_line = graphics::Line::new_round(color, TURN_ICON_ARROW_THICKNESS);

View File

@ -5,7 +5,7 @@
extern crate map_model; extern crate map_model;
use animation; use animation;
use colors::ColorScheme; use colors::{ColorScheme, Colors};
use control::ControlMap; use control::ControlMap;
use ezgui::ToggleableLayer; use ezgui::ToggleableLayer;
use ezgui::canvas; use ezgui::canvas;
@ -64,7 +64,8 @@ pub struct UI {
color_picker: ColorPicker, color_picker: ColorPicker,
canvas: Canvas, canvas: Canvas,
color_scheme: ColorScheme, // TODO maybe never pass this to other places? Always resolve colors here?
cs: ColorScheme,
} }
impl UI { impl UI {
@ -117,7 +118,7 @@ impl UI {
color_picker: ColorPicker::new(), color_picker: ColorPicker::new(),
canvas: Canvas::new(), canvas: Canvas::new(),
color_scheme: ColorScheme::random_settings(), cs: ColorScheme::random_colors(),
}; };
match savestate::load("editor_state") { match savestate::load("editor_state") {
@ -139,7 +140,7 @@ impl UI {
match ColorScheme::load("color_scheme") { match ColorScheme::load("color_scheme") {
Ok(scheme) => { Ok(scheme) => {
println!("Loaded previous color_scheme"); println!("Loaded previous color_scheme");
ui.color_scheme = scheme; ui.cs = scheme;
} }
Err(err) => { Err(err) => {
println!("Couldn't load color_scheme: {}", err); println!("Couldn't load color_scheme: {}", err);
@ -318,7 +319,7 @@ impl UI {
}; };
// TODO maybe make state line up with the map, so loading from a new map doesn't break // TODO maybe make state line up with the map, so loading from a new map doesn't break
savestate::write("editor_state", state).expect("Saving editor_state failed"); savestate::write("editor_state", state).expect("Saving editor_state failed");
self.color_scheme self.cs
.write("color_scheme") .write("color_scheme")
.expect("Saving color_scheme failed"); .expect("Saving color_scheme failed");
println!("Saved editor_state and color_scheme"); println!("Saved editor_state and color_scheme");
@ -341,10 +342,10 @@ impl UI {
for r in &roads_onscreen { for r in &roads_onscreen {
r.draw(g, self.color_road(r.id)); r.draw(g, self.color_road(r.id));
if self.canvas.cam_zoom >= MIN_ZOOM_FOR_ROAD_MARKERS { if self.canvas.cam_zoom >= MIN_ZOOM_FOR_ROAD_MARKERS {
r.draw_detail(g); r.draw_detail(g, &self.cs);
} }
if self.debug_mode.is_enabled() { if self.debug_mode.is_enabled() {
r.draw_debug(g, self.geom_map.get_r(r.id)); r.draw_debug(g, &self.cs, self.geom_map.get_r(r.id));
} }
} }
@ -356,7 +357,7 @@ impl UI {
if self.show_icons.is_enabled() { if self.show_icons.is_enabled() {
for t in &self.draw_map.get_turn_icons_onscreen(screen_bbox) { for t in &self.draw_map.get_turn_icons_onscreen(screen_bbox) {
t.draw_icon(g, self.color_turn_icon(t.id)); t.draw_icon(g, self.color_turn_icon(t.id), &self.cs);
for c in &self.sim_ctrl for c in &self.sim_ctrl
.sim .sim
.get_draw_cars_on_turn(t.id, &self.geom_map) .get_draw_cars_on_turn(t.id, &self.geom_map)
@ -394,6 +395,7 @@ impl UI {
&self.draw_map, &self.draw_map,
&self.control_map, &self.control_map,
&self.sim_ctrl.sim, &self.sim_ctrl.sim,
&self.cs,
g, g,
); );
@ -489,17 +491,19 @@ impl UI {
fn color_road(&self, id: map_model::RoadID) -> Color { fn color_road(&self, id: map_model::RoadID) -> Color {
let r = self.map.get_r(id); let r = self.map.get_r(id);
let default = match r.lane_type { let default = match r.lane_type {
map_model::LaneType::Driving => render::ROAD_COLOR, map_model::LaneType::Driving => self.cs.get(Colors::Road),
map_model::LaneType::Parking => render::PARKING_COLOR, map_model::LaneType::Parking => self.cs.get(Colors::Parking),
map_model::LaneType::Sidewalk => render::SIDEWALK_COLOR, map_model::LaneType::Sidewalk => self.cs.get(Colors::Sidewalk),
}; };
// TODO This evaluates all the color methods, which may be expensive. But the option // TODO This evaluates all the color methods, which may be expensive. But the option
// chaining is harder to read. :( // chaining is harder to read. :(
vec![ vec![
self.current_selection_state.color_r(r), self.current_selection_state.color_r(r, &self.cs),
self.current_search_state.color_r(r), self.current_search_state.color_r(r, &self.cs),
self.floodfiller.as_ref().and_then(|f| f.color_r(r)), self.floodfiller
.as_ref()
.and_then(|f| f.color_r(r, &self.cs)),
if self.steepness_active.is_enabled() { if self.steepness_active.is_enabled() {
self.steepness_viz.color_r(&self.map, r) self.steepness_viz.color_r(&self.map, r)
} else { } else {
@ -521,29 +525,31 @@ impl UI {
// TODO weird to squeeze in some quick logic here? // TODO weird to squeeze in some quick logic here?
let default_color = if let Some(s) = self.control_map.traffic_signals.get(&i.id) { let default_color = if let Some(s) = self.control_map.traffic_signals.get(&i.id) {
if s.changed() { if s.changed() {
render::CHANGED_TRAFFIC_SIGNAL_INTERSECTION_COLOR self.cs.get(Colors::ChangedTrafficSignalIntersection)
} else { } else {
render::TRAFFIC_SIGNAL_INTERSECTION_COLOR self.cs.get(Colors::TrafficSignalIntersection)
} }
} else if let Some(s) = self.control_map.stop_signs.get(&i.id) { } else if let Some(s) = self.control_map.stop_signs.get(&i.id) {
if s.changed() { if s.changed() {
render::CHANGED_STOP_SIGN_INTERSECTION_COLOR self.cs.get(Colors::ChangedStopSignIntersection)
} else { } else {
render::NORMAL_INTERSECTION_COLOR self.cs.get(Colors::NormalIntersection)
} }
} else { } else {
render::NORMAL_INTERSECTION_COLOR self.cs.get(Colors::NormalIntersection)
}; };
self.current_selection_state self.current_selection_state
.color_i(i) .color_i(i, &self.cs)
.unwrap_or(default_color) .unwrap_or(default_color)
} }
fn color_turn_icon(&self, id: map_model::TurnID) -> Color { fn color_turn_icon(&self, id: map_model::TurnID) -> Color {
let t = self.map.get_t(id); let t = self.map.get_t(id);
// TODO traffic signal selection logic maybe moves here // TODO traffic signal selection logic maybe moves here
self.current_selection_state.color_t(t).unwrap_or_else(|| { self.current_selection_state
.color_t(t, &self.cs)
.unwrap_or_else(|| {
self.stop_sign_editor self.stop_sign_editor
.as_ref() .as_ref()
.and_then(|e| e.color_t(t, &self.control_map)) .and_then(|e| e.color_t(t, &self.control_map))
@ -554,7 +560,7 @@ impl UI {
.unwrap_or_else(|| { .unwrap_or_else(|| {
self.turn_colors self.turn_colors
.color_t(t) .color_t(t)
.unwrap_or(render::TURN_ICON_INACTIVE_COLOR) .unwrap_or(self.cs.get(Colors::TurnIconInactive))
}) })
}) })
}) })
@ -563,8 +569,8 @@ impl UI {
fn color_building(&self, id: map_model::BuildingID) -> Color { fn color_building(&self, id: map_model::BuildingID) -> Color {
let b = self.map.get_b(id); let b = self.map.get_b(id);
vec![ vec![
self.current_selection_state.color_b(b), self.current_selection_state.color_b(b, &self.cs),
self.current_search_state.color_b(b), self.current_search_state.color_b(b, &self.cs),
if self.osm_classifier_active.is_enabled() { if self.osm_classifier_active.is_enabled() {
self.osm_classifier.color_b(b) self.osm_classifier.color_b(b)
} else { } else {
@ -573,17 +579,20 @@ impl UI {
].iter() ].iter()
.filter_map(|c| *c) .filter_map(|c| *c)
.next() .next()
.unwrap_or(render::BUILDING_COLOR) .unwrap_or(self.cs.get(Colors::Building))
} }
// Returns (boundary, fill) color // Returns (boundary, fill) color
fn color_parcel(&self, id: map_model::ParcelID) -> (Color, Color) { fn color_parcel(&self, id: map_model::ParcelID) -> (Color, Color) {
let _p = self.map.get_p(id); let _p = self.map.get_p(id);
(render::PARCEL_BOUNDARY_COLOR, render::PARCEL_INTERIOR_COLOR) (
self.cs.get(Colors::ParcelBoundary),
self.cs.get(Colors::ParcelInterior),
)
} }
fn color_car(&self, id: CarID) -> Color { fn color_car(&self, id: CarID) -> Color {
if let Some(c) = self.current_selection_state.color_c(id) { if let Some(c) = self.current_selection_state.color_c(id, &self.cs) {
return c; return c;
} }
if self.sim_ctrl.sim.is_moving(id) { if self.sim_ctrl.sim.is_moving(id) {

View File

@ -10,7 +10,6 @@ use piston::input::{Button, Event, Key, MouseButton, MouseCursorEvent, MouseScro
PressEvent, ReleaseEvent}; PressEvent, ReleaseEvent};
use piston::window::Size; use piston::window::Size;
//pub const WHITE: Color = [1.0, 1.0, 1.0, 1.0];
pub const BLACK: Color = [0.0, 0.0, 0.0, 1.0]; pub const BLACK: Color = [0.0, 0.0, 0.0, 1.0];
pub const BLUE: Color = [0.0, 0.0, 1.0, 1.0]; pub const BLUE: Color = [0.0, 0.0, 1.0, 1.0];
pub const YELLOW: Color = [1.0, 1.0, 0.0, 1.0]; pub const YELLOW: Color = [1.0, 1.0, 0.0, 1.0];
@ -22,9 +21,7 @@ pub const DARK_GREY: Color = [0.3, 0.3, 0.3, 1.0];
pub const PURPLE: Color = [0.5, 0.0, 0.5, 1.0]; pub const PURPLE: Color = [0.5, 0.0, 0.5, 1.0];
pub const CYAN: Color = [0.0, 1.0, 1.0, 1.0]; pub const CYAN: Color = [0.0, 1.0, 1.0, 1.0];
pub const LIGHT_BROWN: Color = [210.0 / 255.0, 105.0 / 255.0, 30.0 / 255.0, 1.0]; pub const LIGHT_BROWN: Color = [210.0 / 255.0, 105.0 / 255.0, 30.0 / 255.0, 1.0];
// TODO it'd be a bit more efficient to not render it at all...
pub const ALMOST_INVISIBLE: Color = [0.0, 0.0, 0.0, 0.1]; pub const ALMOST_INVISIBLE: Color = [0.0, 0.0, 0.0, 0.1];
//pub const INVISIBLE: Color = [0.0, 0.0, 0.0, 0.0];
const TEXT_FG_COLOR: Color = BLACK; const TEXT_FG_COLOR: Color = BLACK;
const TEXT_BG_COLOR: Color = [0.0, 1.0, 0.0, 0.5]; const TEXT_BG_COLOR: Color = [0.0, 1.0, 0.0, 0.5];