mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-01 19:27:11 +03:00
move existing points in a drawn polygon
This commit is contained in:
parent
8b0fb9248c
commit
0cd27d7f50
124
editor/src/plugins/draw_polygon.rs
Normal file
124
editor/src/plugins/draw_polygon.rs
Normal file
@ -0,0 +1,124 @@
|
||||
use ezgui::{Canvas, GfxCtx, TextBox, UserInput};
|
||||
use geom::{Circle, Line, Polygon, Pt2D};
|
||||
use piston::input::{Button, Key, ReleaseEvent};
|
||||
use plugins::Colorizer;
|
||||
|
||||
const POINT_RADIUS: f64 = 2.0;
|
||||
|
||||
pub enum DrawPolygonState {
|
||||
Empty,
|
||||
// Option<usize> is the point currently being hovered over
|
||||
DrawingPoints(Vec<Pt2D>, Option<usize>),
|
||||
MovingPoint(Vec<Pt2D>, usize),
|
||||
NamingPolygon(TextBox, Vec<Pt2D>),
|
||||
}
|
||||
|
||||
impl DrawPolygonState {
|
||||
pub fn new() -> DrawPolygonState {
|
||||
DrawPolygonState::Empty
|
||||
}
|
||||
|
||||
pub fn event(&mut self, input: &mut UserInput, canvas: &Canvas) -> bool {
|
||||
let mut new_state: Option<DrawPolygonState> = None;
|
||||
match self {
|
||||
DrawPolygonState::Empty => {
|
||||
if input.unimportant_key_pressed(Key::N, "start drawing a polygon") {
|
||||
new_state = Some(DrawPolygonState::DrawingPoints(Vec::new(), None));
|
||||
}
|
||||
}
|
||||
DrawPolygonState::DrawingPoints(ref mut pts, ref mut current_idx) => {
|
||||
if input.key_pressed(Key::Escape, "throw away this neighborhood polygon") {
|
||||
new_state = Some(DrawPolygonState::Empty);
|
||||
} else if input.key_pressed(Key::P, "add a new point here") {
|
||||
pts.push(canvas.get_cursor_in_map_space());
|
||||
} else if pts.len() >= 3
|
||||
&& input.key_pressed(Key::Return, "confirm the polygon's shape")
|
||||
{
|
||||
new_state = Some(DrawPolygonState::NamingPolygon(TextBox::new(), pts.clone()));
|
||||
}
|
||||
|
||||
if new_state.is_none() {
|
||||
let cursor = canvas.get_cursor_in_map_space();
|
||||
*current_idx = pts
|
||||
.iter()
|
||||
.position(|pt| Circle::new(*pt, POINT_RADIUS).contains_pt(cursor));
|
||||
if let Some(idx) = current_idx {
|
||||
// TODO mouse dragging might be more intuitive, but it's unclear how to
|
||||
// override part of canvas.handle_event
|
||||
if input.key_pressed(Key::LCtrl, "hold to move this point") {
|
||||
new_state = Some(DrawPolygonState::MovingPoint(pts.clone(), *idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DrawPolygonState::MovingPoint(ref mut pts, idx) => {
|
||||
pts[*idx] = canvas.get_cursor_in_map_space();
|
||||
if let Some(Button::Keyboard(Key::LCtrl)) =
|
||||
input.use_event_directly().release_args()
|
||||
{
|
||||
new_state = Some(DrawPolygonState::DrawingPoints(pts.clone(), Some(*idx)));
|
||||
}
|
||||
}
|
||||
DrawPolygonState::NamingPolygon(tb, pts) => {
|
||||
if tb.event(input.use_event_directly()) {
|
||||
println!("TODO: save neighborhood {} with points {:?}", tb.line, pts);
|
||||
new_state = Some(DrawPolygonState::Empty);
|
||||
}
|
||||
input.consume_event();
|
||||
}
|
||||
}
|
||||
if let Some(s) = new_state {
|
||||
*self = s;
|
||||
}
|
||||
match self {
|
||||
DrawPolygonState::Empty => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_osd_lines(&self) -> Vec<String> {
|
||||
// TODO draw the cursor
|
||||
if let DrawPolygonState::NamingPolygon(tb, _) = self {
|
||||
return vec![tb.line.clone()];
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
pub fn draw(&self, g: &mut GfxCtx) {
|
||||
// TODO add colorscheme entries
|
||||
let red = [1.0, 0.0, 0.0, 1.0];
|
||||
let green = [0.0, 1.0, 0.0, 1.0];
|
||||
let blue = [0.0, 0.0, 1.0, 1.0];
|
||||
let cyan = [0.0, 1.0, 1.0, 1.0];
|
||||
|
||||
let (pts, current_idx) = match self {
|
||||
DrawPolygonState::Empty => {
|
||||
return;
|
||||
}
|
||||
DrawPolygonState::DrawingPoints(pts, current_idx) => (pts, *current_idx),
|
||||
DrawPolygonState::MovingPoint(pts, idx) => (pts, Some(*idx)),
|
||||
DrawPolygonState::NamingPolygon(_, pts) => {
|
||||
g.draw_polygon(blue, &Polygon::new(pts));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if pts.len() == 2 {
|
||||
g.draw_line(red, POINT_RADIUS / 2.0, &Line::new(pts[0], pts[1]));
|
||||
}
|
||||
if pts.len() >= 3 {
|
||||
g.draw_polygon(blue, &Polygon::new(pts));
|
||||
}
|
||||
for pt in pts {
|
||||
g.draw_circle(red, &Circle::new(*pt, POINT_RADIUS));
|
||||
}
|
||||
if let Some(last) = pts.last() {
|
||||
g.draw_circle(green, &Circle::new(*last, POINT_RADIUS));
|
||||
}
|
||||
if let Some(idx) = current_idx {
|
||||
g.draw_circle(cyan, &Circle::new(pts[idx], POINT_RADIUS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Colorizer for DrawPolygonState {}
|
@ -1,13 +1,13 @@
|
||||
pub mod classification;
|
||||
pub mod color_picker;
|
||||
pub mod debug_objects;
|
||||
pub mod draw_polygon;
|
||||
pub mod floodfill;
|
||||
pub mod follow;
|
||||
pub mod geom_validation;
|
||||
pub mod hider;
|
||||
pub mod road_editor;
|
||||
pub mod search;
|
||||
pub mod select_polygon;
|
||||
pub mod show_route;
|
||||
pub mod sim_controls;
|
||||
pub mod steep;
|
||||
|
@ -1,93 +0,0 @@
|
||||
use ezgui::{Canvas, GfxCtx, TextBox, UserInput};
|
||||
use geom::{Circle, Line, Polygon, Pt2D};
|
||||
use piston::input::Key;
|
||||
use plugins::Colorizer;
|
||||
|
||||
pub enum SelectPolygonState {
|
||||
Empty,
|
||||
SelectingPoints(Vec<Pt2D>),
|
||||
NamingPolygon(TextBox, Vec<Pt2D>),
|
||||
}
|
||||
|
||||
impl SelectPolygonState {
|
||||
pub fn new() -> SelectPolygonState {
|
||||
SelectPolygonState::Empty
|
||||
}
|
||||
|
||||
pub fn event(&mut self, input: &mut UserInput, canvas: &Canvas) -> bool {
|
||||
let mut new_state: Option<SelectPolygonState> = None;
|
||||
match self {
|
||||
SelectPolygonState::Empty => {
|
||||
if input.unimportant_key_pressed(Key::N, "start drawing a polygon") {
|
||||
new_state = Some(SelectPolygonState::SelectingPoints(Vec::new()));
|
||||
}
|
||||
}
|
||||
SelectPolygonState::SelectingPoints(ref mut pts) => {
|
||||
if input.key_pressed(Key::Escape, "throw away this neighborhood polygon") {
|
||||
new_state = Some(SelectPolygonState::Empty);
|
||||
} else if input.key_pressed(Key::P, "add a new point here") {
|
||||
pts.push(canvas.get_cursor_in_map_space());
|
||||
} else if pts.len() >= 3
|
||||
&& input.key_pressed(Key::Return, "confirm the polygon's shape")
|
||||
{
|
||||
new_state = Some(SelectPolygonState::NamingPolygon(
|
||||
TextBox::new(),
|
||||
pts.clone(),
|
||||
));
|
||||
}
|
||||
// TODO move existing points
|
||||
}
|
||||
SelectPolygonState::NamingPolygon(tb, pts) => {
|
||||
if tb.event(input.use_event_directly()) {
|
||||
println!("TODO: save neighborhood {} with points {:?}", tb.line, pts);
|
||||
new_state = Some(SelectPolygonState::Empty);
|
||||
}
|
||||
input.consume_event();
|
||||
}
|
||||
}
|
||||
if let Some(s) = new_state {
|
||||
*self = s;
|
||||
}
|
||||
match self {
|
||||
SelectPolygonState::Empty => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_osd_lines(&self) -> Vec<String> {
|
||||
// TODO draw the cursor
|
||||
if let SelectPolygonState::NamingPolygon(tb, _) = self {
|
||||
return vec![tb.line.clone()];
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
pub fn draw(&self, g: &mut GfxCtx) {
|
||||
let pts = match self {
|
||||
SelectPolygonState::Empty => {
|
||||
return;
|
||||
}
|
||||
SelectPolygonState::SelectingPoints(pts) => pts,
|
||||
SelectPolygonState::NamingPolygon(_, pts) => pts,
|
||||
};
|
||||
|
||||
// TODO add colorscheme entries
|
||||
let red = [1.0, 0.0, 0.0, 1.0];
|
||||
let green = [0.0, 1.0, 0.0, 1.0];
|
||||
let blue = [0.0, 0.0, 1.0, 1.0];
|
||||
let radius = 2.0;
|
||||
|
||||
if pts.len() == 2 {
|
||||
g.draw_line(red, radius / 2.0, &Line::new(pts[0], pts[1]));
|
||||
}
|
||||
if pts.len() >= 3 {
|
||||
g.draw_polygon(blue, &Polygon::new(pts));
|
||||
}
|
||||
for pt in pts {
|
||||
g.draw_circle(red, &Circle::new(*pt, radius));
|
||||
}
|
||||
g.draw_circle(green, &Circle::new(*pts.last().unwrap(), radius));
|
||||
}
|
||||
}
|
||||
|
||||
impl Colorizer for SelectPolygonState {}
|
@ -18,13 +18,13 @@ use piston::window::Size;
|
||||
use plugins::classification::OsmClassifier;
|
||||
use plugins::color_picker::ColorPicker;
|
||||
use plugins::debug_objects::DebugObjectsState;
|
||||
use plugins::draw_polygon::DrawPolygonState;
|
||||
use plugins::floodfill::Floodfiller;
|
||||
use plugins::follow::FollowState;
|
||||
use plugins::geom_validation::Validator;
|
||||
use plugins::hider::Hider;
|
||||
use plugins::road_editor::RoadEditor;
|
||||
use plugins::search::SearchState;
|
||||
use plugins::select_polygon::SelectPolygonState;
|
||||
use plugins::show_route::ShowRouteState;
|
||||
use plugins::sim_controls::SimController;
|
||||
use plugins::steep::SteepnessVisualizer;
|
||||
@ -122,7 +122,7 @@ impl UIWrapper {
|
||||
color_picker: ColorPicker::new(),
|
||||
geom_validator: Validator::new(),
|
||||
turn_cycler: TurnCyclerState::new(),
|
||||
select_polygon: SelectPolygonState::new(),
|
||||
draw_polygon: DrawPolygonState::new(),
|
||||
|
||||
active_plugin: None,
|
||||
|
||||
@ -236,7 +236,7 @@ impl UIWrapper {
|
||||
.event(input, &mut ui.canvas, &ui.map, &ui.draw_map)
|
||||
}),
|
||||
Box::new(|ui, input| ui.turn_cycler.event(input, ui.current_selection)),
|
||||
Box::new(|ui, input| ui.select_polygon.event(input, &ui.canvas)),
|
||||
Box::new(|ui, input| ui.draw_polygon.event(input, &ui.canvas)),
|
||||
],
|
||||
}
|
||||
}
|
||||
@ -268,7 +268,7 @@ struct UI {
|
||||
color_picker: ColorPicker,
|
||||
geom_validator: Validator,
|
||||
turn_cycler: TurnCyclerState,
|
||||
select_polygon: SelectPolygonState,
|
||||
draw_polygon: DrawPolygonState,
|
||||
|
||||
// An index into UIWrapper.plugins.
|
||||
active_plugin: Option<usize>,
|
||||
@ -446,7 +446,7 @@ impl UI {
|
||||
self.debug_objects
|
||||
.draw(&self.map, &self.canvas, &self.draw_map, &self.sim, g);
|
||||
self.color_picker.draw(&self.canvas, g);
|
||||
self.select_polygon.draw(g);
|
||||
self.draw_polygon.draw(g);
|
||||
|
||||
// TODO Only if active (except for the weird sim_ctrl)?
|
||||
let mut osd_lines = self.sim_ctrl.get_osd_lines(&self.sim);
|
||||
@ -465,10 +465,10 @@ impl UI {
|
||||
osd_lines.push(String::from(""));
|
||||
osd_lines.extend(warp_lines);
|
||||
}
|
||||
let select_lines = self.select_polygon.get_osd_lines();
|
||||
if !select_lines.is_empty() {
|
||||
let draw_poly_lines = self.draw_polygon.get_osd_lines();
|
||||
if !draw_poly_lines.is_empty() {
|
||||
osd_lines.push(String::from(""));
|
||||
osd_lines.extend(select_lines);
|
||||
osd_lines.extend(draw_poly_lines);
|
||||
}
|
||||
self.canvas.draw_osd_notification(g, &osd_lines);
|
||||
}
|
||||
@ -518,7 +518,7 @@ impl UI {
|
||||
13 => Some(Box::new(&self.floodfiller)),
|
||||
14 => Some(Box::new(&self.geom_validator)),
|
||||
15 => Some(Box::new(&self.turn_cycler)),
|
||||
16 => Some(Box::new(&self.select_polygon)),
|
||||
16 => Some(Box::new(&self.draw_polygon)),
|
||||
_ => panic!("Active plugin {} is too high", idx),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user