From f4aa9780e0a426ffd2f5661bffd7814d4cb324fc Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Mon, 2 Jun 2025 16:52:32 -0500 Subject: [PATCH] delete last town is just the inverse of create town --- rsrc/dialogs/delete-town-confirm.xml | 3 +-- src/scenedit/scen.townout.cpp | 9 ++++++--- src/scenedit/scen.undo.cpp | 16 +++++++++------- src/scenedit/scen.undo.hpp | 26 +++++++++++++++----------- src/tools/undo.cpp | 4 ++-- src/tools/undo.hpp | 4 +++- 6 files changed, 36 insertions(+), 26 deletions(-) diff --git a/rsrc/dialogs/delete-town-confirm.xml b/rsrc/dialogs/delete-town-confirm.xml index 07394417..b5f4addb 100644 --- a/rsrc/dialogs/delete-town-confirm.xml +++ b/rsrc/dialogs/delete-town-confirm.xml @@ -8,12 +8,11 @@ You are about to delete the last town in your scenario's town list (so if you have 10 towns in your scenario, the tenth will disappear). - This change will immediately be saved, and can't be undone. - Are you sure you want to do this? Make sure to remove all outdoor entrances to the deleted town, as well as all references to it in special encounters. Failure to do so will result in scenario run-time errors. + Are you sure you want to do this? diff --git a/src/scenedit/scen.townout.cpp b/src/scenedit/scen.townout.cpp index 923d4f55..9f4aef64 100644 --- a/src/scenedit/scen.townout.cpp +++ b/src/scenedit/scen.townout.cpp @@ -48,6 +48,7 @@ extern cUndoList undo_list; extern std::string help_text_rsrc; extern bool editing_town; extern bool last_shift_continuous; +extern void update_edit_menu(); const char *day_str_1[] = {"Unused","Day creature appears","Day creature disappears", "Unused","Unused","Unused","Unused","Unused","Unused"}; @@ -1671,7 +1672,8 @@ bool new_town() { for(short j = 0; j < town->max_dim; j++) town->terrain(i,j) = preset; - undo_list.add(action_ptr(new aNewTown(scenario.towns.back()))); + undo_list.add(action_ptr(new aCreateDeleteTown(true, scenario.towns.back()))); + update_edit_menu(); change_made = true; return true; @@ -1679,9 +1681,10 @@ bool new_town() { // before calling this, be sure to do all checks to make sure it's safe. void delete_last_town() { - cTown* last_town = scenario.towns.back(); + undo_list.add(action_ptr(new aCreateDeleteTown(false, scenario.towns.back()))); + update_edit_menu(); + scenario.towns.pop_back(); - delete last_town; change_made = true; } diff --git a/src/scenedit/scen.undo.cpp b/src/scenedit/scen.undo.cpp index f9e4a157..adb049f8 100644 --- a/src/scenedit/scen.undo.cpp +++ b/src/scenedit/scen.undo.cpp @@ -14,6 +14,7 @@ extern cArea* get_current_area(); extern void start_town_edit(); extern void start_out_edit(); extern void redraw_screen(); +extern void set_current_town(int,bool first_restore = false); cTerrainAction::cTerrainAction(std::string name, short town_num, location where) : cAction(name) { area.is_town = true; @@ -72,24 +73,25 @@ bool aEraseSpecial::redo_me() { return true; } -aNewTown::aNewTown(cTown* t) - : cAction("Add Town") +aCreateDeleteTown::aCreateDeleteTown(bool create, cTown* t) + : cAction(create ? "Create Town" : "Delete Last Town", !create) , theTown(t) {} -bool aNewTown::undo_me() { +bool aCreateDeleteTown::undo_me() { scenario.towns.resize(scenario.towns.size() - 1); - cur_town = min(cur_town, scenario.towns.size() - 1); + set_current_town(min(cur_town, scenario.towns.size() - 1)); return true; } -bool aNewTown::redo_me() { +bool aCreateDeleteTown::redo_me() { scenario.towns.push_back(theTown); + set_current_town(scenario.towns.size() - 1); return true; } -aNewTown::~aNewTown() { - if(!isDone()) delete theTown; +aCreateDeleteTown::~aCreateDeleteTown() { + if(isDone() == reversed) delete theTown; } bool aDrawTerrain::undo_me() { diff --git a/src/scenedit/scen.undo.hpp b/src/scenedit/scen.undo.hpp index 4d77a0e2..5984f584 100644 --- a/src/scenedit/scen.undo.hpp +++ b/src/scenedit/scen.undo.hpp @@ -19,7 +19,7 @@ struct ter_change_t { typedef std::map stroke_ter_changes_t; -// Action that modified town or outdoor terrain, so we should show the modified area when undoing or redoing +// Action that modified something in town or outdoor terrain, so we should show the modified area when undoing or redoing class cTerrainAction : public cAction { public: cTerrainAction(std::string name, short town_num, location where); @@ -35,16 +35,7 @@ private: area_ref_t area; }; -/// Represents the action of adding a new town to the end of the list -class aNewTown : public cAction { - class cTown* theTown; - bool undo_me() override; - bool redo_me() override; -public: - aNewTown(class cTown* t); - ~aNewTown(); -}; - +/// Action that erased a special encounter from a spot class aEraseSpecial : public cTerrainAction { public: aEraseSpecial(spec_loc_t special) : cTerrainAction("Erase Special Encounter", special), for_redo(special) {} @@ -55,6 +46,7 @@ private: bool editing_town; }; +/// Action which modifies terrain tiles (i.e. paintbrush, pencil, eraser) class aDrawTerrain : public cTerrainAction { public: aDrawTerrain(std::string name, stroke_ter_changes_t stroke_changes) : @@ -66,4 +58,16 @@ private: const stroke_ter_changes_t changes; }; +/// Action which adds a new town to the end of the list, or deletes the last one +class aCreateDeleteTown : public cAction { + bool created; + class cTown* theTown; + bool undo_me() override; + bool redo_me() override; +public: + aCreateDeleteTown(bool create, class cTown* t); + ~aCreateDeleteTown(); +}; + + #endif \ No newline at end of file diff --git a/src/tools/undo.cpp b/src/tools/undo.cpp index 12771e2b..2b6dbf9c 100644 --- a/src/tools/undo.cpp +++ b/src/tools/undo.cpp @@ -23,13 +23,13 @@ cAction::~cAction() {} void cAction::undo() { UNDO_LOG("Undoing " + actname); - if(done && undo_me()) + if(done && reversed ? redo_me() : undo_me()) done = false; } void cAction::redo() { UNDO_LOG("Redoing " + actname); - if(!done && redo_me()) + if(!done && reversed ? undo_me() : redo_me()) done = true; } diff --git a/src/tools/undo.hpp b/src/tools/undo.hpp index f0bbae44..b2e51350 100644 --- a/src/tools/undo.hpp +++ b/src/tools/undo.hpp @@ -23,7 +23,9 @@ class cAction { protected: /// Construct a named action /// @param name The name of the action to show in the Edit menu - cAction(std::string name) : actname(name) {} + cAction(std::string name, bool reversed = false) : actname(name), reversed(reversed) {} + /// For actions that have an inverse, this flag inverts the action implementation (i.e. create/delete) + bool reversed = true; public: /// Undoes this action if it has not already been undone. /// If it has already been undone, does nothing.