mirror of
https://github.com/a-b-street/abstreet.git
synced 2025-01-03 03:47:23 +03:00
Undo/redo in the new road editor
This commit is contained in:
parent
8dbb1a47e5
commit
e0871d9db2
@ -1,11 +1,11 @@
|
||||
use geom::Distance;
|
||||
use map_gui::render::{Renderable, OUTLINE_THICKNESS};
|
||||
use map_model::{
|
||||
Direction, EditRoad, LaneID, LaneSpec, LaneType, Road, RoadID, NORMAL_LANE_THICKNESS,
|
||||
Direction, EditCmd, EditRoad, LaneID, LaneSpec, LaneType, Road, RoadID, NORMAL_LANE_THICKNESS,
|
||||
};
|
||||
use widgetry::{
|
||||
Choice, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome,
|
||||
Panel, State, Text, TextExt, VerticalAlignment, Widget,
|
||||
lctrl, Choice, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line,
|
||||
Outcome, Panel, State, Text, TextExt, VerticalAlignment, Widget,
|
||||
};
|
||||
|
||||
use crate::app::{App, Transition};
|
||||
@ -17,20 +17,18 @@ pub struct RoadEditor {
|
||||
top_panel: Panel,
|
||||
main_panel: Panel,
|
||||
highlight_selection: (Option<LaneID>, Drawable),
|
||||
|
||||
// Undo/redo management
|
||||
num_edit_cmds_originally: usize,
|
||||
redo_stack: Vec<EditCmd>,
|
||||
}
|
||||
|
||||
impl RoadEditor {
|
||||
pub fn new(ctx: &mut EventCtx, app: &mut App, r: RoadID) -> Box<dyn State<App>> {
|
||||
app.primary.current_selection = None;
|
||||
|
||||
let top_panel = Panel::new(Widget::row(vec![ctx
|
||||
.style()
|
||||
.btn_solid_primary
|
||||
.text("Finish")
|
||||
.hotkey(Key::Escape)
|
||||
.build_def(ctx)]))
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
.build(ctx);
|
||||
let num_edit_cmds_originally = app.primary.map.get_edits().commands.len();
|
||||
let top_panel = make_top_panel(ctx, app, num_edit_cmds_originally, true);
|
||||
let current_lane = None;
|
||||
let main_panel = make_main_panel(ctx, app, app.primary.map.get_r(r), current_lane);
|
||||
let highlight_selection = highlight_current_selection(ctx, app, r, current_lane);
|
||||
@ -40,6 +38,9 @@ impl RoadEditor {
|
||||
top_panel,
|
||||
main_panel,
|
||||
highlight_selection,
|
||||
|
||||
num_edit_cmds_originally,
|
||||
redo_stack: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -61,6 +62,7 @@ impl RoadEditor {
|
||||
.commands
|
||||
.push(app.primary.map.edit_road_cmd(self.r, |new| (f)(new, idx)));
|
||||
apply_map_edits(ctx, app, edits);
|
||||
self.redo_stack.clear();
|
||||
|
||||
self.current_lane = if let Some(offset) = select_new_lane_offset {
|
||||
Some(app.primary.map.get_r(self.r).lanes_ltr()[((idx as isize) + offset) as usize].0)
|
||||
@ -71,6 +73,12 @@ impl RoadEditor {
|
||||
self.main_panel =
|
||||
make_main_panel(ctx, app, app.primary.map.get_r(self.r), self.current_lane);
|
||||
self.highlight_selection = highlight_current_selection(ctx, app, self.r, self.current_lane);
|
||||
self.top_panel = make_top_panel(
|
||||
ctx,
|
||||
app,
|
||||
self.num_edit_cmds_originally,
|
||||
self.redo_stack.is_empty(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,6 +91,40 @@ impl State<App> for RoadEditor {
|
||||
"Finish" => {
|
||||
return Transition::Pop;
|
||||
}
|
||||
"undo" => {
|
||||
let mut edits = app.primary.map.get_edits().clone();
|
||||
self.redo_stack.push(edits.commands.pop().unwrap());
|
||||
apply_map_edits(ctx, app, edits);
|
||||
|
||||
self.current_lane = None;
|
||||
self.main_panel =
|
||||
make_main_panel(ctx, app, app.primary.map.get_r(self.r), self.current_lane);
|
||||
self.highlight_selection =
|
||||
highlight_current_selection(ctx, app, self.r, self.current_lane);
|
||||
self.top_panel = make_top_panel(
|
||||
ctx,
|
||||
app,
|
||||
self.num_edit_cmds_originally,
|
||||
self.redo_stack.is_empty(),
|
||||
);
|
||||
}
|
||||
"redo" => {
|
||||
let mut edits = app.primary.map.get_edits().clone();
|
||||
edits.commands.push(self.redo_stack.pop().unwrap());
|
||||
apply_map_edits(ctx, app, edits);
|
||||
|
||||
self.current_lane = None;
|
||||
self.main_panel =
|
||||
make_main_panel(ctx, app, app.primary.map.get_r(self.r), self.current_lane);
|
||||
self.highlight_selection =
|
||||
highlight_current_selection(ctx, app, self.r, self.current_lane);
|
||||
self.top_panel = make_top_panel(
|
||||
ctx,
|
||||
app,
|
||||
self.num_edit_cmds_originally,
|
||||
self.redo_stack.is_empty(),
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => {}
|
||||
@ -131,6 +173,7 @@ impl State<App> for RoadEditor {
|
||||
});
|
||||
}));
|
||||
apply_map_edits(ctx, app, edits);
|
||||
self.redo_stack.clear();
|
||||
|
||||
assert!(self.current_lane.is_none());
|
||||
self.current_lane =
|
||||
@ -139,6 +182,12 @@ impl State<App> for RoadEditor {
|
||||
make_main_panel(ctx, app, app.primary.map.get_r(self.r), self.current_lane);
|
||||
self.highlight_selection =
|
||||
highlight_current_selection(ctx, app, self.r, self.current_lane);
|
||||
self.top_panel = make_top_panel(
|
||||
ctx,
|
||||
app,
|
||||
self.num_edit_cmds_originally,
|
||||
self.redo_stack.is_empty(),
|
||||
);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
@ -153,10 +202,17 @@ impl State<App> for RoadEditor {
|
||||
new.speed_limit = speed_limit;
|
||||
}));
|
||||
apply_map_edits(ctx, app, edits);
|
||||
self.redo_stack.clear();
|
||||
|
||||
// Lane IDs don't change
|
||||
self.main_panel =
|
||||
make_main_panel(ctx, app, app.primary.map.get_r(self.r), self.current_lane);
|
||||
self.top_panel = make_top_panel(
|
||||
ctx,
|
||||
app,
|
||||
self.num_edit_cmds_originally,
|
||||
self.redo_stack.is_empty(),
|
||||
);
|
||||
} else {
|
||||
let width = self.main_panel.dropdown_value("width");
|
||||
self.modify_current_lane(ctx, app, Some(0), |new, idx| {
|
||||
@ -198,6 +254,36 @@ impl State<App> for RoadEditor {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_top_panel(
|
||||
ctx: &mut EventCtx,
|
||||
app: &App,
|
||||
num_edit_cmds_originally: usize,
|
||||
no_redo_cmds: bool,
|
||||
) -> Panel {
|
||||
Panel::new(Widget::row(vec![
|
||||
ctx.style()
|
||||
.btn_solid_primary
|
||||
.text("Finish")
|
||||
.hotkey(Key::Escape)
|
||||
.build_def(ctx),
|
||||
ctx.style()
|
||||
.btn_plain
|
||||
.icon("system/assets/tools/undo.svg")
|
||||
.disabled(app.primary.map.get_edits().commands.len() == num_edit_cmds_originally)
|
||||
.hotkey(lctrl(Key::Z))
|
||||
.build_widget(ctx, "undo"),
|
||||
ctx.style()
|
||||
.btn_plain
|
||||
.icon("system/assets/tools/redo.svg")
|
||||
.disabled(no_redo_cmds)
|
||||
// TODO ctrl+shift+Z!
|
||||
.hotkey(lctrl(Key::Y))
|
||||
.build_widget(ctx, "redo"),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
.build(ctx)
|
||||
}
|
||||
|
||||
fn make_main_panel(
|
||||
ctx: &mut EventCtx,
|
||||
app: &App,
|
||||
|
Loading…
Reference in New Issue
Block a user