Autosave even the untitled edits!

Possibly when the player explicitly says "discard proposal", we should
actually delete the file.
This commit is contained in:
Dustin Carlino 2020-09-14 14:25:09 -07:00
parent 0a3479a3d0
commit d68273086b
8 changed files with 59 additions and 35 deletions

View File

@ -226,7 +226,7 @@ impl State for EditMode {
true,
Some(Transition::Pop),
Box::new(|ctx, app| {
apply_map_edits(ctx, app, MapEdits::new());
apply_map_edits(ctx, app, app.primary.map.new_edits());
}),
)),
"save this proposal as..." => Transition::Replace(SaveEdits::new(
@ -245,7 +245,7 @@ impl State for EditMode {
app.primary.map.get_name(),
&app.primary.map.get_edits().edits_name,
));
apply_map_edits(ctx, app, MapEdits::new());
apply_map_edits(ctx, app, app.primary.map.new_edits());
Transition::Pop
}
_ => unreachable!(),
@ -430,13 +430,13 @@ impl State for SaveEdits {
.must_apply_edits(edits, &mut Timer::new("name map edits"));
app.primary.map.save_edits();
if self.reset {
apply_map_edits(ctx, app, MapEdits::new());
apply_map_edits(ctx, app, app.primary.map.new_edits());
}
(self.on_success)(ctx, app);
return Transition::Pop;
}
"Discard proposal" => {
apply_map_edits(ctx, app, MapEdits::new());
apply_map_edits(ctx, app, app.primary.map.new_edits());
return Transition::Pop;
}
"Cancel" => {
@ -516,7 +516,7 @@ impl State for LoadEdits {
match x.as_ref() {
"close" => Transition::Pop,
"Start over with blank proposal" => {
apply_map_edits(ctx, app, MapEdits::new());
apply_map_edits(ctx, app, app.primary.map.new_edits());
Transition::Pop
}
path => {
@ -648,9 +648,7 @@ pub fn apply_map_edits(ctx: &mut EventCtx, app: &mut App, edits: MapEdits) {
}
// Autosave
if app.primary.map.get_edits().edits_name != "Untitled Proposal" {
app.primary.map.save_edits();
}
app.primary.map.save_edits();
}
pub fn can_edit_lane(mode: &GameplayMode, l: LaneID, app: &App) -> bool {
@ -739,7 +737,6 @@ fn make_changelist(ctx: &mut EventCtx, app: &App) -> Panel {
"manage proposals",
lctrl(Key::P),
),
// TODO This is a lie for untitled proposals right now, need to pick names for those
"autosaved"
.draw_text(ctx)
.container()

View File

@ -361,7 +361,7 @@ impl State for FinalScore {
if self.chose_next || self.chose_back_to_challenges {
ctx.loading_screen("reset map and sim", |ctx, mut timer| {
// Always safe to do this
apply_map_edits(ctx, app, MapEdits::new());
apply_map_edits(ctx, app, app.primary.map.new_edits());
app.primary
.map
.recalculate_pathfinding_after_edits(&mut timer);

View File

@ -21,7 +21,6 @@ use crate::pregame::MainMenu;
use crate::render::UnzoomedAgents;
pub use gameplay::{spawn_agents_around, GameplayMode, TutorialPointer, TutorialState};
use geom::Time;
use map_model::MapEdits;
use maplit::btreeset;
use sim::AgentType;
pub use speed::{SpeedControls, TimePanel};
@ -279,7 +278,7 @@ impl State for BackToMainMenu {
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
ctx.loading_screen("reset map and sim", |ctx, mut timer| {
// Always safe to do this
apply_map_edits(ctx, app, MapEdits::new());
apply_map_edits(ctx, app, app.primary.map.new_edits());
app.primary
.map
.recalculate_pathfinding_after_edits(&mut timer);

View File

@ -85,10 +85,9 @@ pub struct EditEffects {
}
impl MapEdits {
pub fn new() -> MapEdits {
pub(crate) fn new() -> MapEdits {
MapEdits {
// Something has to fill this out later
edits_name: "Untitled Proposal".to_string(),
edits_name: "TODO temporary".to_string(),
proposal_description: Vec::new(),
proposal_link: None,
commands: Vec::new(),
@ -114,7 +113,10 @@ impl MapEdits {
// TODO Version these? Or it's unnecessary, since we have a command stack.
fn save(&self, map: &Map) {
assert_ne!(self.edits_name, "Untitled Proposal");
// If untitled and empty, don't actually save anything.
if self.edits_name.starts_with("Untitled Proposal") && self.commands.is_empty() {
return;
}
abstutil::write_json(
abstutil::path_edits(map.get_name(), &self.edits_name),
@ -403,10 +405,29 @@ fn recalculate_turns(
}
impl Map {
pub fn new_edits(&self) -> MapEdits {
let mut edits = MapEdits::new();
// Automatically find a new filename
let mut i = 1;
loop {
let name = format!("Untitled Proposal {}", i);
if !abstutil::file_exists(abstutil::path_edits(&self.name, &name)) {
edits.edits_name = name;
return edits;
}
i += 1;
}
}
pub fn get_edits(&self) -> &MapEdits {
&self.edits
}
pub fn unsaved_edits(&self) -> bool {
self.edits.edits_name.starts_with("Untitled Proposal") && !self.edits.commands.is_empty()
}
pub fn get_r_edit(&self, r: RoadID) -> EditRoad {
let r = self.get_r(r);
EditRoad {

View File

@ -53,6 +53,7 @@ impl Map {
name: raw.name.clone(),
edits: MapEdits::new(),
};
map.edits = map.new_edits();
let road_id_mapping: BTreeMap<OriginalRoad, RoadID> = initial_map
.roads

View File

@ -29,7 +29,8 @@ impl Map {
if path.starts_with(&abstutil::path_all_maps()) {
match abstutil::maybe_read_binary(path.clone(), timer) {
Ok(map) => {
let map: Map = map;
let mut map: Map = map;
map.edits = map.new_edits();
if false {
use abstutil::{prettyprint_usize, serialized_size_bytes};
@ -458,12 +459,8 @@ impl Map {
result
}
pub fn unsaved_edits(&self) -> bool {
self.edits.edits_name == "Untitled Proposal" && !self.edits.commands.is_empty()
}
pub fn save(&self) {
assert_eq!(self.edits.edits_name, "Untitled Proposal");
assert!(self.edits.edits_name.starts_with("Untitled Proposal"));
assert!(self.edits.commands.is_empty());
assert!(!self.pathfinder_dirty);
abstutil::write_binary(abstutil::path_map(&self.name), self);

View File

@ -88,17 +88,27 @@ impl SimFlags {
let mut sim: Sim = abstutil::read_binary(self.load.clone(), timer);
let mut map = Map::new(abstutil::path_map(&sim.map_name), timer);
if sim.edits_name != "Untitled Proposal" {
map.must_apply_edits(
MapEdits::load(
&map,
abstutil::path_edits(map.get_name(), &sim.edits_name),
timer,
)
.unwrap(),
timer,
);
map.recalculate_pathfinding_after_edits(timer);
match MapEdits::load(
&map,
abstutil::path_edits(map.get_name(), &sim.edits_name),
timer,
) {
Ok(edits) => {
map.must_apply_edits(edits, timer);
map.recalculate_pathfinding_after_edits(timer);
}
Err(err) => {
// Little brittle. Sometimes legitimate edits wind up being saved without a
// proper name.
if sim.edits_name.starts_with("Untitled Proposal") {
warn!(
"Sim savestate refers to edits \"{}\", but not using them: {}",
sim.edits_name, err
);
} else {
panic!("Couldn't load edits \"{}\": {}", sim.edits_name, err);
}
}
}
sim.restore_paths(&map, timer);

View File

@ -143,8 +143,7 @@ impl Sim {
time: Time::START_OF_DAY,
map_name: map.get_name().to_string(),
// TODO
edits_name: "Untitled Proposal".to_string(),
edits_name: map.get_edits().edits_name.clone(),
run_name: opts.run_name,
step_count: 0,
alerts: opts.alerts,