mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-29 17:34:58 +03:00
support for modifying individual existing points of a road. no attempt to save these changes reasonably yet.
This commit is contained in:
parent
3fd74673cf
commit
125a8fde98
@ -16,6 +16,7 @@ enum State {
|
|||||||
Viewing,
|
Viewing,
|
||||||
MovingIntersection(StableIntersectionID),
|
MovingIntersection(StableIntersectionID),
|
||||||
MovingBuilding(StableBuildingID),
|
MovingBuilding(StableBuildingID),
|
||||||
|
MovingRoadPoint(StableRoadID, usize),
|
||||||
LabelingBuilding(StableBuildingID, Wizard),
|
LabelingBuilding(StableBuildingID, Wizard),
|
||||||
LabelingRoad((StableRoadID, Direction), Wizard),
|
LabelingRoad((StableRoadID, Direction), Wizard),
|
||||||
LabelingIntersection(StableIntersectionID, Wizard),
|
LabelingIntersection(StableIntersectionID, Wizard),
|
||||||
@ -71,6 +72,14 @@ impl GUI for UI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
State::MovingRoadPoint(r, idx) => {
|
||||||
|
if let Some(cursor) = ctx.canvas.get_cursor_in_map_space() {
|
||||||
|
self.model.move_r_pt(r, idx, cursor, ctx.prerender);
|
||||||
|
if ctx.input.key_released(Key::LeftControl) {
|
||||||
|
self.state = State::Viewing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
State::LabelingBuilding(id, ref mut wizard) => {
|
State::LabelingBuilding(id, ref mut wizard) => {
|
||||||
if let Some(label) = wizard.wrap(ctx).input_string_prefilled(
|
if let Some(label) = wizard.wrap(ctx).input_string_prefilled(
|
||||||
"Label the building",
|
"Label the building",
|
||||||
@ -194,6 +203,18 @@ impl GUI for UI {
|
|||||||
self.model.handle_mouseover(ctx);
|
self.model.handle_mouseover(ctx);
|
||||||
} else if ctx.input.key_pressed(Key::L, "label side of the road") {
|
} else if ctx.input.key_pressed(Key::L, "label side of the road") {
|
||||||
self.state = State::LabelingRoad((r, dir), Wizard::new());
|
self.state = State::LabelingRoad((r, dir), Wizard::new());
|
||||||
|
} else if self.model.showing_pts.is_none()
|
||||||
|
&& ctx.input.key_pressed(Key::P, "move road points")
|
||||||
|
{
|
||||||
|
self.model.show_r_points(r, ctx.prerender);
|
||||||
|
self.model.handle_mouseover(ctx);
|
||||||
|
}
|
||||||
|
} else if let Some(ID::RoadPoint(r, idx)) = self.model.get_selection() {
|
||||||
|
if ctx.input.key_pressed(Key::LeftControl, "move point") {
|
||||||
|
self.state = State::MovingRoadPoint(r, idx);
|
||||||
|
} else if ctx.input.key_pressed(Key::Backspace, "delete point") {
|
||||||
|
self.model.delete_r_pt(r, idx, ctx.prerender);
|
||||||
|
self.model.handle_mouseover(ctx);
|
||||||
}
|
}
|
||||||
} else if ctx.input.unimportant_key_pressed(Key::Escape, "quit") {
|
} else if ctx.input.unimportant_key_pressed(Key::Escape, "quit") {
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
@ -215,6 +236,10 @@ impl GUI for UI {
|
|||||||
self.model.handle_mouseover(ctx);
|
self.model.handle_mouseover(ctx);
|
||||||
} else if cursor.is_some() && ctx.input.key_pressed(Key::LeftShift, "select area") {
|
} else if cursor.is_some() && ctx.input.key_pressed(Key::LeftShift, "select area") {
|
||||||
self.state = State::SelectingRectangle(cursor.unwrap(), cursor.unwrap(), true);
|
self.state = State::SelectingRectangle(cursor.unwrap(), cursor.unwrap(), true);
|
||||||
|
} else if self.model.showing_pts.is_some()
|
||||||
|
&& ctx.input.key_pressed(Key::P, "stop moving road points")
|
||||||
|
{
|
||||||
|
self.model.stop_showing_pts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
State::SelectingRectangle(pt1, ref mut pt2, ref mut keydown) => {
|
State::SelectingRectangle(pt1, ref mut pt2, ref mut keydown) => {
|
||||||
@ -287,7 +312,9 @@ impl GUI for UI {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
State::MovingIntersection(_) | State::MovingBuilding(_) => {}
|
State::MovingIntersection(_)
|
||||||
|
| State::MovingBuilding(_)
|
||||||
|
| State::MovingRoadPoint(_, _) => {}
|
||||||
State::SelectingRectangle(pt1, pt2, _) => {
|
State::SelectingRectangle(pt1, pt2, _) => {
|
||||||
if let Some(rect) = Polygon::rectangle_two_corners(pt1, pt2) {
|
if let Some(rect) = Polygon::rectangle_two_corners(pt1, pt2) {
|
||||||
g.draw_polygon(Color::BLUE.alpha(0.5), &rect);
|
g.draw_polygon(Color::BLUE.alpha(0.5), &rect);
|
||||||
|
@ -26,6 +26,8 @@ pub struct Model {
|
|||||||
// Never reuse IDs, and don't worry about being sequential
|
// Never reuse IDs, and don't worry about being sequential
|
||||||
id_counter: usize,
|
id_counter: usize,
|
||||||
all_fixes: BTreeMap<String, MapFixes>,
|
all_fixes: BTreeMap<String, MapFixes>,
|
||||||
|
// TODO Not sure this should be pub...
|
||||||
|
pub showing_pts: Option<StableRoadID>,
|
||||||
|
|
||||||
exclude_bldgs: bool,
|
exclude_bldgs: bool,
|
||||||
edit_fixes: Option<String>,
|
edit_fixes: Option<String>,
|
||||||
@ -40,6 +42,7 @@ impl Model {
|
|||||||
roads_per_intersection: MultiMap::new(),
|
roads_per_intersection: MultiMap::new(),
|
||||||
id_counter: 0,
|
id_counter: 0,
|
||||||
all_fixes: BTreeMap::new(),
|
all_fixes: BTreeMap::new(),
|
||||||
|
showing_pts: None,
|
||||||
|
|
||||||
exclude_bldgs: false,
|
exclude_bldgs: false,
|
||||||
edit_fixes: None,
|
edit_fixes: None,
|
||||||
@ -351,6 +354,7 @@ impl Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Roads
|
||||||
impl Model {
|
impl Model {
|
||||||
fn road_added(&mut self, id: StableRoadID, prerender: &Prerender) {
|
fn road_added(&mut self, id: StableRoadID, prerender: &Prerender) {
|
||||||
for obj in self.lanes(id) {
|
for obj in self.lanes(id) {
|
||||||
@ -527,6 +531,7 @@ impl Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_r(&mut self, id: StableRoadID) {
|
pub fn delete_r(&mut self, id: StableRoadID) {
|
||||||
|
assert!(self.showing_pts != Some(id));
|
||||||
self.road_deleted(id);
|
self.road_deleted(id);
|
||||||
|
|
||||||
let r = self.map.roads.remove(&id).unwrap();
|
let r = self.map.roads.remove(&id).unwrap();
|
||||||
@ -624,8 +629,67 @@ impl Model {
|
|||||||
color
|
color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn show_r_points(&mut self, id: StableRoadID, prerender: &Prerender) {
|
||||||
|
assert_eq!(self.showing_pts, None);
|
||||||
|
self.showing_pts = Some(id);
|
||||||
|
|
||||||
|
let r = &self.map.roads[&id];
|
||||||
|
for (idx, pt) in r.center_points.iter().enumerate() {
|
||||||
|
// Don't show handles for the intersections
|
||||||
|
if idx != 0 && idx != r.center_points.len() - 1 {
|
||||||
|
self.world.add(
|
||||||
|
prerender,
|
||||||
|
Object::new(
|
||||||
|
ID::RoadPoint(id, idx),
|
||||||
|
Color::GREEN,
|
||||||
|
Circle::new(*pt, INTERSECTION_RADIUS / 2.0).to_polygon(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stop_showing_pts(&mut self) {
|
||||||
|
let id = self.showing_pts.take().unwrap();
|
||||||
|
|
||||||
|
let r = &self.map.roads[&id];
|
||||||
|
for idx in 1..=r.center_points.len() - 2 {
|
||||||
|
self.world.delete(ID::RoadPoint(id, idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn move_r_pt(&mut self, id: StableRoadID, idx: usize, point: Pt2D, prerender: &Prerender) {
|
||||||
|
assert_eq!(self.showing_pts, Some(id));
|
||||||
|
|
||||||
|
self.stop_showing_pts();
|
||||||
|
self.road_deleted(id);
|
||||||
|
|
||||||
|
self.map.roads.get_mut(&id).unwrap().center_points[idx] = point;
|
||||||
|
|
||||||
|
self.road_added(id, prerender);
|
||||||
|
self.show_r_points(id, prerender);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_r_pt(&mut self, id: StableRoadID, idx: usize, prerender: &Prerender) {
|
||||||
|
assert_eq!(self.showing_pts, Some(id));
|
||||||
|
|
||||||
|
self.stop_showing_pts();
|
||||||
|
self.road_deleted(id);
|
||||||
|
|
||||||
|
self.map
|
||||||
|
.roads
|
||||||
|
.get_mut(&id)
|
||||||
|
.unwrap()
|
||||||
|
.center_points
|
||||||
|
.remove(idx);
|
||||||
|
|
||||||
|
self.road_added(id, prerender);
|
||||||
|
self.show_r_points(id, prerender);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Buildings
|
||||||
impl Model {
|
impl Model {
|
||||||
fn bldg_added(&mut self, id: StableBuildingID, prerender: &Prerender) {
|
fn bldg_added(&mut self, id: StableBuildingID, prerender: &Prerender) {
|
||||||
let b = &self.map.buildings[&id];
|
let b = &self.map.buildings[&id];
|
||||||
@ -694,6 +758,7 @@ pub enum ID {
|
|||||||
Building(StableBuildingID),
|
Building(StableBuildingID),
|
||||||
Intersection(StableIntersectionID),
|
Intersection(StableIntersectionID),
|
||||||
Lane(StableRoadID, Direction, usize),
|
Lane(StableRoadID, Direction, usize),
|
||||||
|
RoadPoint(StableRoadID, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectID for ID {
|
impl ObjectID for ID {
|
||||||
@ -702,6 +767,7 @@ impl ObjectID for ID {
|
|||||||
ID::Lane(_, _, _) => 0,
|
ID::Lane(_, _, _) => 0,
|
||||||
ID::Intersection(_) => 1,
|
ID::Intersection(_) => 1,
|
||||||
ID::Building(_) => 2,
|
ID::Building(_) => 2,
|
||||||
|
ID::RoadPoint(_, _) => 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user