one key to toggle lane types

This commit is contained in:
Dustin Carlino 2018-12-08 13:57:03 -08:00
parent e71fa25229
commit 7363302d5d
2 changed files with 92 additions and 105 deletions

View File

@ -1,6 +1,6 @@
use crate::objects::{EDIT_MAP, ID};
use crate::plugins::{Plugin, PluginCtx};
use map_model::{EditReason, LaneID, LaneType};
use map_model::{EditReason, Lane, LaneID, LaneType, MapEdits, Road};
use piston::input::Key;
pub struct RoadEditor {}
@ -20,93 +20,89 @@ impl RoadEditor {
impl Plugin for RoadEditor {
fn blocking_event(&mut self, ctx: &mut PluginCtx) -> bool {
let (input, selected, map, draw_map, sim) = (
&mut ctx.input,
ctx.primary.current_selection,
&mut ctx.primary.map,
&mut ctx.primary.draw_map,
&mut ctx.primary.sim,
);
let mut edits = map.get_edits().clone();
// TODO a bit awkward that we can't pull this info from edits easily
let mut changed: Option<(LaneID, LaneType)> = None;
if input.key_pressed(Key::Return, "stop editing roads") {
if ctx.input.key_pressed(Key::Return, "stop editing roads") {
return false;
} else if let Some(ID::Lane(id)) = selected {
let lane = map.get_l(id);
let road = map.get_r(lane.parent);
} else if let Some(ID::Lane(id)) = ctx.primary.current_selection {
let lane = ctx.primary.map.get_l(id);
let road = ctx.primary.map.get_r(lane.parent);
let reason = EditReason::BasemapWrong; // TODO be able to choose
if lane.lane_type != LaneType::Sidewalk {
if lane.lane_type != LaneType::Driving
&& input.key_pressed(Key::D, "make this a driving lane")
if lane.lane_type == LaneType::Sidewalk {
return true;
}
if ctx.input.key_pressed(Key::Backspace, "delete this lane") {
let mut edits = ctx.primary.map.get_edits().clone();
edits.delete_lane(road, lane);
warn!("Have to reload the map from scratch to pick up this change!");
ctx.primary.map.store_new_edits(edits);
} else if let Some(new_type) = next_valid_type(ctx.primary.map.get_edits(), road, lane)
{
if ctx
.input
.key_pressed(Key::Space, &format!("toggle to {:?}", new_type))
{
if edits.change_lane_type(reason, road, lane, LaneType::Driving) {
changed = Some((lane.id, LaneType::Driving));
}
}
if lane.lane_type != LaneType::Parking
&& input.key_pressed(Key::P, "make this a parking lane")
{
if edits.change_lane_type(reason, road, lane, LaneType::Parking) {
changed = Some((lane.id, LaneType::Parking));
}
}
if lane.lane_type != LaneType::Biking
&& input.key_pressed(Key::B, "make this a bike lane")
{
if edits.change_lane_type(reason, road, lane, LaneType::Biking) {
changed = Some((lane.id, LaneType::Biking));
}
}
if lane.lane_type != LaneType::Bus
&& input.key_pressed(Key::U, "make this a bus lane")
{
if edits.change_lane_type(reason, road, lane, LaneType::Bus) {
changed = Some((lane.id, LaneType::Bus));
}
}
if input.key_pressed(Key::Backspace, "delete this lane") {
if edits.delete_lane(road, lane) {
warn!("Have to reload the map from scratch to pick up this change!");
}
let mut edits = ctx.primary.map.get_edits().clone();
edits.change_lane_type(reason, road, lane, new_type);
change_lane_type(lane.id, new_type, ctx);
ctx.primary.map.store_new_edits(edits);
}
}
}
if let Some((id, new_type)) = changed {
let intersections = map.get_l(id).intersections();
// TODO generally tense about having two methods to carry out this change. weird
// intermediate states are scary. maybe pass old and new struct for intersection (aka
// list of turns)?
// Remove turns
for i in &intersections {
for t in &map.get_i(*i).turns {
draw_map.edit_remove_turn(*t);
sim.edit_remove_turn(map.get_t(*t));
}
}
// TODO Pretty sure control layer needs to recalculate based on the new turns
let old_type = map.get_l(id).lane_type;
map.edit_lane_type(id, new_type);
draw_map.edit_lane_type(id, map);
sim.edit_lane_type(id, old_type, map);
// Add turns back
for i in &intersections {
for t in &map.get_i(*i).turns {
draw_map.edit_add_turn(*t, map);
sim.edit_add_turn(map.get_t(*t));
}
}
}
map.store_new_edits(edits);
true
}
}
fn next_valid_type(edits: &MapEdits, r: &Road, lane: &Lane) -> Option<LaneType> {
let mut new_type = next_type(lane.lane_type);
while new_type != lane.lane_type {
if edits.can_change_lane_type(r, lane, new_type) {
return Some(new_type);
}
new_type = next_type(new_type);
}
None
}
fn next_type(lt: LaneType) -> LaneType {
match lt {
LaneType::Driving => LaneType::Parking,
LaneType::Parking => LaneType::Biking,
LaneType::Biking => LaneType::Bus,
LaneType::Bus => LaneType::Driving,
LaneType::Sidewalk => panic!("next_type(Sidewalk) undefined; can't modify sidewalks"),
}
}
fn change_lane_type(id: LaneID, new_type: LaneType, ctx: &mut PluginCtx) {
let intersections = ctx.primary.map.get_l(id).intersections();
// TODO generally tense about having two methods to carry out this change. weird intermediate
// states are scary. maybe pass old and new struct for intersection (aka list of turns)?
// Remove turns
for i in &intersections {
for t in &ctx.primary.map.get_i(*i).turns {
ctx.primary.draw_map.edit_remove_turn(*t);
ctx.primary.sim.edit_remove_turn(ctx.primary.map.get_t(*t));
}
}
// TODO Pretty sure control layer needs to recalculate based on the new turns
let old_type = ctx.primary.map.get_l(id).lane_type;
ctx.primary.map.edit_lane_type(id, new_type);
ctx.primary.draw_map.edit_lane_type(id, &ctx.primary.map);
ctx.primary
.sim
.edit_lane_type(id, old_type, &ctx.primary.map);
// Add turns back
for i in &intersections {
for t in &ctx.primary.map.get_i(*i).turns {
ctx.primary.draw_map.edit_add_turn(*t, &ctx.primary.map);
ctx.primary.sim.edit_add_turn(ctx.primary.map.get_t(*t));
}
}
}

View File

@ -40,26 +40,23 @@ impl MapEdits {
abstutil::save_object("edits", &self.map_name, &self.edits_name, self);
}
pub fn can_change_lane_type(&self, r: &Road, lane: &Lane, new_type: LaneType) -> bool {
RoadEdit::change_lane_type(EditReason::BasemapWrong, r, lane, new_type).is_some()
}
pub fn change_lane_type(
&mut self,
reason: EditReason,
r: &Road,
lane: &Lane,
new_type: LaneType,
) -> bool {
if let Some(edit) = RoadEdit::change_lane_type(reason, r, lane, new_type) {
self.roads.insert(r.id, edit);
return true;
}
false
) {
let edit = RoadEdit::change_lane_type(reason, r, lane, new_type).unwrap();
self.roads.insert(r.id, edit);
}
pub fn delete_lane(&mut self, r: &Road, lane: &Lane) -> bool {
if let Some(edit) = RoadEdit::delete_lane(r, lane) {
self.roads.insert(r.id, edit);
return true;
}
false
pub fn delete_lane(&mut self, r: &Road, lane: &Lane) {
self.roads.insert(r.id, RoadEdit::delete_lane(r, lane));
}
}
@ -78,7 +75,6 @@ pub struct RoadEdit {
}
impl RoadEdit {
// TODO return Result, so we can enforce a reason coming back!
fn change_lane_type(
reason: EditReason,
r: &Road,
@ -86,16 +82,14 @@ impl RoadEdit {
new_type: LaneType,
) -> Option<RoadEdit> {
if lane.is_sidewalk() {
error!("Sidewalks are fixed; can't change their type");
return None;
panic!("Sidewalks are fixed; can't change their type");
}
let (mut forwards, mut backwards) = r.get_lane_types();
let (is_fwd, idx) = r.dir_and_offset(lane.id);
if is_fwd {
if forwards[idx] == new_type {
error!("{} is already {:?}", lane.id, new_type);
return None;
panic!("{} is already {:?}", lane.id, new_type);
}
forwards[idx] = new_type;
if !are_lanes_valid(&forwards) {
@ -103,8 +97,7 @@ impl RoadEdit {
}
} else {
if backwards[idx] == new_type {
error!("{} is already {:?}", lane.id, new_type);
return None;
panic!("{} is already {:?}", lane.id, new_type);
}
backwards[idx] = new_type;
if !are_lanes_valid(&backwards) {
@ -120,11 +113,9 @@ impl RoadEdit {
})
}
fn delete_lane(r: &Road, lane: &Lane) -> Option<RoadEdit> {
// Sidewalks are fixed
fn delete_lane(r: &Road, lane: &Lane) -> RoadEdit {
if lane.is_sidewalk() {
error!("Can't delete sidewalks");
return None;
panic!("Can't delete sidewalks");
}
let (mut forwards, mut backwards) = r.get_lane_types();
@ -135,12 +126,12 @@ impl RoadEdit {
backwards.remove(idx);
}
Some(RoadEdit {
RoadEdit {
road: r.id,
forwards_lanes: forwards,
backwards_lanes: backwards,
reason: EditReason::BasemapWrong,
})
}
}
}